原址地址:http://ibupu.link/?id=29
1. 迪傑斯特拉算法簡介
迪傑斯特拉(dijkstra)算法是典型的用來解決最短路徑的算法,也是很多教程中的范例,由荷蘭計算機科學家狄克斯特拉於1959年提出,用來求得從起始點到其他所有點最短路徑。該算法采用了貪心的思想,每次都查找與該點距離最近的點,也因為這樣,它不能用來解決存在負權邊的圖。解決的問題大多是這樣的:有一個無向圖G(V,E),邊E[i]的權值為W[i],找出V[0]到V[i]的最短路徑。
3. 迪傑斯特拉算法的原理
①首先,引入一個輔助向量D,它的每個分量D[i]表示當前所找到的 Dijkstra算法運行動畫過程 Dijkstra算法運行動畫過程 從起始點 (即源點 )到其它每個頂點 的長度。例如,D[3] = 2表示從起始點到頂點3的路徑相對最小長度為2。這里強調相對就是說在算法執行過程中D的值是在不斷逼近最終結果但在過程中不一定就等於長度。
②D的初始狀態為:若從v 到v[i]有弧(即從v到v[i]存在連接邊),則D[i]為弧上的權值(即為從v到v[i]的邊的權值);否則置D[i]為∞。顯然,長度為 D[j]= Min{ D |v[i]∈V } 的路徑就是從v出發到頂點v[j]的長度最短的一條路徑,此路徑為(v,v[j])。
③那么,下一條長度次短的是哪一條呢?也就是找到從源點v到下一個頂點的最短路徑長度所對應的頂點,且這條最短路徑長度僅次於從源點v到頂點v[j]的最短路徑長度。 假設該次短路徑的終點是v[k],則可想而知,這條路徑要么是(v,v[k]),或者是(v,v[j],v[k])。它的長度或者是從v到v[k]的弧上的權值,或者是D[j]加上從v[j]到v[k]的弧上的權值。
④一般情況下,假設S為已求得的從源點v出發的最短路徑長度的頂點的集合,則可證明:下一條次最短路徑(設其終點為x)要么是弧(v,x),或者是從源點v出發的中間只經過S中的頂點而最后到達頂點 的路徑。 因此,下一條長度次短的的最短路徑長度必是D[j]= Min{ D[i] |v[i]∈V-S },其中D 要么是弧( v,v[i])上的權值,或者是D[i]( v[k]∈S)和弧(v[k] ,v[i] )上的權值之和。
3. 迪傑斯特拉算法的實現過程
①先取一點v[0]作為起始點,初始化dis[i],d[i]的值為v[0]到其余點v[i]的距離w[0][i],如果直接相鄰初始化為權值,否則初始化為無限大;
②將v[0]標記,vis[0] = 1(vis一開始初始化為0);
③找尋與v[0]相鄰的最近點v[k],將v[k]點記錄下來,v[k]與v[0]的距離記為min;
④把v[k]標記,vis[k]=1;
⑤查詢並比較,讓dis[j]與min+w[k][j]進行比較,判斷是直接v[0]連接v[j]短,還是經過v[k]連接v[j]更短,即dis[j]=MIN(dis[j],min+w[k][j]);
⑥繼續重復步驟③與步驟⑤,知道找出所有點為止。
4. 迪傑斯特拉的實現代碼(C/C++)
1 int dijkstra(int n) 2 { 3 //初始化v[0]到v[i]的距離 4 for(int i=1;i<=n;i++) 5 dis[i] = w[0][i]; 6 vis[0]=1;//標記v[0]點 7 for(int i = 1; i <= n; i++) 8 { 9 //查找最近點 10 int min = INF,k = 0; 11 for(int j = 0; j <= n; j++) 12 if(!vis[w] && dis[j] < min) 13 min = dis[w],k = j; 14 vis[k] = 1;//標記查找到的最近點 15 //判斷是直接v[0]連接v[j]短,還是經過v[k]連接v[j]更短 16 for(int j = 1; j <= n; j++) 17 if(!vis[j] && min+w[k][j] < dis[j]) 18 d[j] = min+w[k][j]; 19 } 20 return dis[j]; 21 }