1. 程式人生 > >Dijkstra演算法 C++實現

Dijkstra演算法 C++實現

單源最短路徑

對於圖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;
        }
    }    
}