1. 程式人生 > >帶權路徑最短——Dijkstra演算法

帶權路徑最短——Dijkstra演算法

Dijkstra演算法是經典的求取帶權最短路徑的演算法。 它採用貪心的思想,在每一步僅選取一個能夠被確定為從已知頂點到該頂點已經為最短路徑的頂點,並動態地去規劃該頂點到其他頂點的最短路徑距離。 本篇博文演算法思想參考自《資料結構及演算法分析》這本書,並將書本里的思想以及程式碼偽碼給實現了。 圖的實現還是採用鄰接表的方式,比較節省空間。在每一步求取未知的最小路徑的頂點時,可以採用小頂堆來實現,我這裡是採用遍歷的方式,因為頂點結構內包含了是否是未知的標記。 從Dijkstra演算法的原理上看,要設定的變數有:

  1. 要確定頂點是已知還是未知的,所以需要一個Known變數。
  2. 要確定帶權的路徑的長度,需要一個dist變數。
  3. 要確定路徑資訊,所以每一個頂點結構體內部要儲存最短路徑到達此頂點的上一個頂點。
  4. 路徑的權值,就儲存在鄰接錶鏈表節點的weight變數裡。

列印路徑資訊的函式採用遞迴的方式,逐層向上查詢,直到達到起點。 演算法程式碼如下:


#include<cstdio> #include<iostream> #include<queue> using namespace std; #define MAX_VERTEX_NUM 100 #define Vertextype int #define Infinity 0xffff #define NotAVertex -1 typedef struct EdgeNode { int adjVertex; int weight; //鄰接權重 EdgeNode *nextEdgeNode; }EdgeNode; typedef struct VerNode { int Known; Vertextype data; int dist; int path; EdgeNode *firstedge; }VerNode; typedef struct Graph { VerNode verNode[MAX_VERTEX_NUM]; int vertex_num,edge_num; }Graph; void CreateDAG(Graph &G,int n,int e) { int i,j,w,k; G.vertex_num=n; G.edge_num=e; for(i=1;i<=n;i++) { cin>>G.verNode[i].data; G.verNode[i].Known=0; G.verNode[i].dist=Infinity; G.verNode[i].path=-1; G.verNode[i].firstedge=NULL; } for(k=1;k<=e;k++) { EdgeNode *p; p=new EdgeNode; cin>>i>>j>>w; p->adjVertex=j; p->weight=w; p->nextEdgeNode=G.verNode[i].firstedge; G.verNode[i].firstedge=p; } } void Dijkstra(Graph &G,int n,int start) //帶權路徑最短Dijkstra演算法 { VerNode V; EdgeNode *w; int i,j,temp_num,temp_dist; G.verNode[start].dist=0; for(i=1;i<=n;++i) //n個點待查詢 { temp_dist=Infinity; temp_num=0; for(j=1;j<=n;++j) //先尋找未知的最短頂點 { if(G.verNode[j].Known==0 && G.verNode[j].dist<temp_dist) { temp_dist=G.verNode[j].dist; temp_num=j; } } G.verNode[temp_num].Known=1; w=G.verNode[temp_num].firstedge; while(w) { if(G.verNode[w->adjVertex].Known==0) { if(G.verNode[temp_num].dist+w->weight < G.verNode[w->adjVertex].dist) { G.verNode[w->adjVertex].dist = G.verNode[temp_num].dist+w->weight; G.verNode[w->adjVertex].path=G.verNode[temp_num].data; } } w=w->nextEdgeNode; } } } int PrintPath(Graph &G,int n,int end) //列印最短路徑資訊,並返回路徑長度 { if(G.verNode[end].path!=NotAVertex) { PrintPath(G,n,G.verNode[end].path); printf(" => "); } printf("%d",G.verNode[end].data); } int main() { Graph G; CreateDAG(G,7,12); //給出圖的頂點數及邊數量 Dijkstra(G,7,1); //給出頂點數以及起點編號 PrintPath(G,7,6); //給出頂點數以及終點編號 } /***測試資料**** 1 2 3 4 5 6 7 1 2 2 1 4 1 2 4 3 2 5 10 3 1 4 3 6 5 4 3 2 4 5 2 4 6 8 4 7 4 5 7 6 7 6 1 輸出:1 => 4 => 7 => 6 *********************/


檢視原文:http://www.wyblog.cn/2016/12/09/%e5%b8%a6%e6%9d%83%e8%b7%af%e5%be%84%e6%9c%80%e7%9f%ad-dijkstra%e7%ae%97%e6%b3%95/