Dijkstra演算法 C++實現
阿新 • • 發佈:2019-02-14
單源最短路徑
對於圖G =(V,E),給定源點 s 屬於 V ,單源路徑是指從 s 到圖中其他各頂點的最短路徑.
下圖為帶權有向圖,從 v0 到其餘各個頂點的最短路徑如表所示。
源點 | 終點 | 最短路徑 | 路徑長度 |
---|---|---|---|
v0 | v1 | V0->v1 | 12 |
v2 | v0->v2 | 10 | |
v3 | v0->v4->v3 | 50 | |
v4 | v0->v4 | 30 | |
v5 | v0->v4->v3->v5 | 60 |
Dijkstra演算法
設圖的鄰接矩陣為 W ,Dijkstra 演算法首先將圖的頂點集合劃分成兩個集合 S 和 V-S 。
集合 S 表示最短路徑已經確定的頂點集合,其餘的頂點則存放在另一個集合 V-S 中。
初始狀態時,集合 S 至包括源點,即 S = {s} ,表示此時只有源點到自己的最短路徑稱為從源點到頂點 v 到最短路徑,並用陣列 D 來記錄當前所找到的從源點 s 到每個頂點的最短路徑長度,用陣列 path 來記錄到達各個頂點的前驅頂點。
其中,如果從源點 s 到頂點 c 有弧 ,則以弧到權值作為 D[v] 的初始值;否則將 D[v] 的初始為無窮大,path 陣列初始化為 s 。
Dijkstra 演算法每次從尚未確定最短路徑長度的集合 V-S 中取出一個最短特殊路徑長度最小的頂點 u ,將 u 加入集合 S ,同時更新陣列 D 、path 中由 s 可達大各個頂點的最短特殊路徑長度。
更新 D 的策略是,若加進 u 做中間頂點,使得 vi 的最短特殊路徑長度變短,則修改 vi 的最短特殊路徑長度及前驅頂點編號,即當 D[u]+W[u ,vi]
程式碼實現
1.定義一個結構體,用來記錄每個頂點的最短路徑。
struct Path{
string route;
Path(){
route = "";
}
};
2.Dijkstra 演算法的實現
void Dijkstra(int s,int D[]){ int n = VerticesNum(); path = new Path[n]; int i,j; for(i = 0;i<n;i++){ D[i] = matrix[s][i]; path[i].route = "v"+to_string(s) + "-->" + "v" + to_string(i); } Mark[s] = VISITED; D[s] = 0; for(i = 0;i<n;i++){ //找到一條最短的特殊路徑 int min = INFINITY; int k = 0; for(j = 0;j<n;j++){ if(Mark[j]==UNVISITED&&min>D[j]){ min = D[j]; k = j; } } Mark[k] = VISITED; for(Edge e = FirstEdge(k);IsEdge(e);e = NextEdge(e)){ int endVertex = e.end; if(Mark[endVertex]==UNVISITED&&D[endVertex]>(D[k] + e.weight)&&e.weight!=INFINITY){ //更新endVertex的最短特殊路徑 D[endVertex] = D[k] + e.weight; path[endVertex].route = path[k].route + "-->v"+to_string(endVertex); } } } for(int i = 0;i<n;i++){ if(D[i]!=INFINITY){ cout<<path[i].route<<endl; } else{ cout<<"no road"<<endl; } } }