程式設計師必須會的基本演算法8-Dijkstra演算法(迪傑斯特拉演算法)
Dijkstra演算法
迪傑斯特拉(Dijkstra)演算法是典型最短路徑演算法,
用於計算一個結點到其他結點的最短路徑。
它的主要特點是以起始點為中心向外層層擴充套件(廣度優先搜尋思想),直到擴充套件到終點為止。
問題場景
有7個節點(A,B,C,D,E,F,G),
從G點出發,分別走到A,B,C,D,E,F六個節點
各個節點的距離用邊線表示(權),比如A–B距離5
如何計算出G到其它各個節點的最短距離?
如果從其它點出發到各個點的最短距離又是多少?
程式碼解決
package basic;
public class Dijkstra
{
/*
* 看完下面的,我們來總體看下迪傑斯特拉演算法的執行策略
* 首先訪問過的只有一個G,然後找到G能訪問的節點中權重最小的
* 那就是GA,然後將GA看做一個節點,能訪問到的節點中權重最小的
* 那就是GAB,然後又看作一個整體,下一個能訪問到的節點中權重最小的
* 那就是GABE,就是這樣的策略
*/
public static void main(String[] args)
{
// char[] nodes={ 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
// int[][] weight=new int[nodes.length][nodes.length];
// final int N=Integer.MAX_VALUE/2;
//
// weight[0]=new int[]{N,5,7,N,N,N,2};
// weight[1]=new int[]{5,N,N,9,N,N,3};
// weight[2]=new int[]{7,N,N,N,8,N,N};
// weight[3]=new int[]{N,9,N,N,N,4,N};
// weight[4]=new int[]{N,N,8,N,N,5,4};
// weight[5]=new int[]{N,N,N,4,5,N,6};
// weight[6]=new int[]{2,3,N,N,4,6,N};
//上面都是初始化資料
char[] nodes={ 'A', 'B', 'C', 'D', 'E', 'F', 'G' ,'H','I'};
int[][] weight=new int[nodes.length][nodes.length];
final int N=Integer.MAX_VALUE/2;
weight[0]=new int[]{N,5,7,N,N,N,2,N,N};
weight[1]=new int[]{5,N,N,9,N,N,3,N,N};
weight[2]=new int[]{7,N,N,N,8,N,N,N,N};
weight[3]=new int[]{N,9,N,N,N,4,N,2,N};
weight[4]=new int[]{N,N,8,N,N,5,4,N,N};
weight[5]=new int[]{N,N,N,4,5,N,6,N,N};
weight[6]=new int[]{2,3,N,N,4,6,N,N,N};
weight[7]=new int[]{N,N,N,2,N,N,N,N,2};
weight[8]=new int[]{N,N,N,N,N,N,N,2,N};
dijkstra(weight, 6);
}
public static void dijkstra(int[][] weight,int index)
{
//需要三個額外的變數來儲存資料
//這表示這個節點是否是已經被訪問過了
int[] vistied=new int[weight.length];
//這表示路徑是什麼
String[] paths=new String[weight.length];
//這表示從出發點到當前節點的距離是多少
int[] TheLength=new int[weight.length];
//初始化路徑
for(int x=0;x<paths.length;x++)
{
paths[x]=new String(index+"->"+x);
}
//初始化出發點
vistied[index]=1;
TheLength[index]=0;
/*
* 然後是遍歷n-1個節點,因為第一個節點已經遍歷過了
* 這裡每一次都是找和出發點相通的,權重最小的那個節點,
* 然後對它進行深一層的遍歷,看看它走到下一層後的最小路徑是否能更加小
* 在這裡你可能在想第二重的for迴圈會不會沒有進去,就是那個找MinLength的for迴圈
* 然後讓下標temp=-1,其實不會的,在後面的for遍歷下一層的時候會改變下一層圖的遍歷
* 就是比如出發點是第零層,然後MinLength是找第二層節點的最小權重,然後下面的for會
* 根據第二層的最小權重去找第二層到第三層的最小權重,如果是出發點不能到達的節點
* 那麼就肯定在第三層或者更加低的層,那麼在第二層遍歷會修改第三層節點的可達,就是修改權重
* 那麼迴圈後再回到上面的尋找下一個最小權重的沒有訪問過的節點的時候就會可能不是從
* 第二層找起,而是直接到更加低的層次找
*/
for(int x=1;x<weight.length;x++)
{
int MinLength=Integer.MAX_VALUE/2;
int temp=-1;
for(int y=0;y<weight.length;y++)
{
if(vistied[y]==0 && weight[index][y]<MinLength)
{
MinLength=weight[index][y];
temp=y;
}
}
TheLength[temp]=MinLength;
vistied[temp]=1;
/**
* 首先是出發點到index節點的距離,然後index這個節點能訪問的下一層節點
* 如果是從index這個節點出發訪問到的下一層節點的距離加上從出發點到index的距離
* 比從出發點到index下一層節點的距離(這是不經過index節點的,從其他的路線出發的)小,
* 那麼就將這TheLength的陣列對應的index下一層節點對應的位置進行修改
*/
for(int y=0;y<weight.length;y++)
{
if(vistied[y]==0 && weight[index][temp]+weight[temp][y]<weight[index][y])
{
weight[index][y]=weight[index][temp]+weight[temp][y];
paths[y]=paths[temp]+"->"+y;
}
}
}
for(int x=0;x<paths.length;x++)
{
if(x!=index)
{
System.out.println(index+"到"+x+"的路徑:"+paths[x]+" 權重:"+TheLength[x]);
}
}
}
}
結果
6到0的路徑:6->0 權重:2
6到1的路徑:6->1 權重:3
6到2的路徑:6->0->2 權重:9
6到3的路徑:6->5->3 權重:10
6到4的路徑:6->4 權重:4
6到5的路徑:6->5 權重:6
6到7的路徑:6->5->3->7 權重:12
6到8的路徑:6->5->3->7->8 權重:14
注意
1.迪傑斯特拉演算法只支援非負權的圖
比如上面的例子,如果B-D(-90),那麼在遍歷的時候,首先加入A進入已訪問的陣列裡面,然後又將B加入到已訪問陣列裡面,那麼就會確定G到A最小距離是2,到B是3,而不是經過B-D這條線,迪傑斯特拉不會重新計算已經算好最小權重的節點,
2.節點之間不可達用Integer.MAX_VALUE代表
因為兩個Integer.MAX_VALUE相加會溢位導致出現負權
相關文章
- 迪傑斯特拉演算法感悟演算法
- 求最短路徑-----迪傑斯特拉演算法演算法
- 最短路徑—Dijkstra(迪傑斯特拉)演算法演算法
- dijkstra迪傑斯特拉演算法(鄰接表法)演算法
- 資料結構與演算法——迪傑斯特拉(Dijkstra)演算法資料結構演算法
- 資料結構 最短路徑之—迪傑斯特拉演算法資料結構演算法
- 資料結構學習筆記-迪傑斯特拉演算法資料結構筆記演算法
- 路徑規劃演算法 - 求解最短路徑 - Dijkstra(迪傑斯特拉)演算法演算法
- C++迪傑斯特拉演算法求最短路徑的詳細解釋C++演算法
- 最短路-迪傑斯特拉(dijkstra)
- 程式設計師必須掌握哪些演算法?程式設計師演算法
- 演算法(四):圖解狄克斯特拉演算法演算法圖解
- 程式設計師必須掌握的核心演算法有哪些?程式設計師演算法
- 程式設計師成為大佬必須學的演算法程式設計師演算法
- Java程式設計師必須掌握的8大排序演算法Java程式設計師排序演算法
- 你已經是個成熟的程式設計師了,該學會用程式幫自己省錢了————狄克斯特拉演算法程式設計師演算法
- 《演算法圖解》總結第 7 章:狄克斯特拉演算法演算法圖解
- 《圖論》——最短路徑 Dijkstra演算法(戴克斯特拉演算法)圖論演算法
- 程式設計師必須知道的10大基礎實用演算法及其講解程式設計師演算法
- 程式設計師必須知道機器學習與資料探勘十大經典演算法:PageRank演算法篇程式設計師機器學習演算法
- 程式設計師必備演算法——排列組合程式設計師演算法
- 程式設計基本演算法(三)程式設計演算法
- 每個Java程式設計師都必須知道的四種負載均衡演算法Java程式設計師負載演算法
- 優秀程式設計師必須知道的32個演算法,提高你的開發效率程式設計師演算法
- 「乾貨總結」程式設計師必知必會的十大排序演算法程式設計師排序演算法
- 演算法工程師必須要知道的8種常用演算法思想演算法工程師
- 程式設計師必知的10大基礎實用演算法程式設計師演算法
- 看Lucene原始碼必須知道的基本規則和演算法原始碼演算法
- 你必須知道的基礎演算法演算法
- Android程式設計師會遇到的演算法(part 5 字典樹)Android程式設計師演算法
- 程式設計師千萬不要學演算法!程式設計師演算法
- 通過克隆程式目錄方式部署迪斯傑
- 程式設計師必知的10大經典基礎實用演算法程式設計師演算法
- 10個程式設計師必須學會接受的殘酷真相程式設計師
- Android程式設計師會遇到的演算法(part 7 拓撲排序)Android程式設計師演算法排序
- 不會演算法的音樂家,不是一個好程式設計師演算法程式設計師
- Dijkstra迪傑斯特拉求最短路和最短路的條數和各個點權值的最大值
- 演算法工程師必須要知道的面試技能雷達圖演算法工程師面試