資料結構(c++)(第二版) Dijkstra最短路徑演算法 教學示範程式碼出現錯誤!
阿新 • • 發佈:2021-09-13
前言
大學生演算法課程教材 資料結構(c++)的Dijkstra教學演算法案例中,出現了一個 bug 導致演算法不能正常的執行,出錯程式碼只是4行的for迴圈迭代程式碼。
書中只給了關鍵程式碼的部分,其餘皆是虛擬碼,將虛擬碼實現為可執行程式碼。並且運行了教學程式碼,證實了相關錯誤。也給出了能正確執行的for迴圈迭代程式碼。
之後便將過程發給出版社,可一年多了,出版社也沒有回信......
也希望大家也可以討論一下。
Dijkstra最短路徑演算法
Dijkstra最路徑演算法用於求單源點最短路徑問題,問題描述如下:給定帶權有向圖G=(V,E)和源點v屬於V,求從v到G中其餘各頂點的最短路徑。
單源點最短路徑問題的一個應用例項是關於計算機網路傳輸的問題:怎樣找到一種最經濟的方式,從一臺計算機向網上所有其他計算機發送一條訊息。
Dijkstra演算法是應用貪心法進行演算法設計的一個典型例子。
問題
資料結構(c++)(第二版) 版次:2011年6月第2版 印次:2020年1月第25次印刷 清華大學出版社
書中的Dijkstra的實列程式碼(P170-171)出現了'k'無法更新的錯誤,程式碼無法得到最後的正確結果。
'k'是dist[n]中最小值的下標,所以每次'k'的更新都要從S集合之外去尋找,而書中是以 k=0 去更新,在k=0的條件約束下,根本無法進入k的更新,所以在運行了4次之後會退出while() 沒有辦法更新。
#include <iostream> #include <cstring> using namespace std; const int Max=9999; class MGraph { int arc[5][5]; //鄰接矩陣 string vertex[10]; //圖的頂點 int vertexNum; public: MGraph(); //初始化鄰接矩陣 對角元素為0 其他元素為Max void Input(); //輸入書中的 6 -28 進行測試 void Show(); friend void Dijkastra( MGraph G , int v ); }; MGraph::MGraph() { int i,j; vertexNum=5; vertex[0]='a'; //等同於 V0 vertex[1]='b'; vertex[2]='c'; vertex[3]='d'; vertex[4]='e'; vertex[5]='\0'; for(i=0;i<5;i++) { for(j=0;j<5;j++) { arc[i][j]=Max; if(i==j) arc[i][j]=0; } } } void MGraph::Input() { int i,j,d; cout<<"請按順序輸入 本書 圖 6-28 (b)鄰接矩陣的 行 列 權值 輸入的行列大於等於5退出"<<endl; cin>>i>>j>>d; while((i<5)&&(j<5)) { arc[i][j]=d; cout<<"請按順序輸入 鄰接矩陣的 行 列 權值"<<endl; cin>>i>>j>>d; } } void MGraph::Show() { int i,j; for(i=0;i<5;i++) { for(j=0;j<5;j++) { cout<<arc[i][j]<<" "; } cout<<endl; } } void Dijkastra( MGraph G , int v ) { int i=0,k; int dist[10]; int s[5]; int num; string path[10]; for (i=0; i<G.vertexNum; i++) { dist[i]=G.arc[v][i]; if (dist[i]!=Max) path[i]=G.vertex[v]+G.vertex[i]; else path[i]=""; } s[0]=v; //初始化集合 S dist[v]=0; //標記頂點 v 為源點 num=1; while(num<G.vertexNum) //當頂點數num小於圖的頂點數 { // 使用時 這兩個for迴圈使用其中一個 即可得到對應結果 // 可以成功實現的迭代程式碼 /*for(i=0;i<G.vertexNum;i++) //修改後的 k 的迭代 ************************************* { if(dist[i]!=0) { k=i; break; } }*/ // 書中的教學程式碼 for(i=0;i<G.vertexNum;i++) //在dist中查詢最小元素 ** k 無法更新! { if((dist[i]!=0)&&(dist[i]<dist[k])) k=i; } cout<<dist[k]<<" "<<path[k]<<endl; s[num++]=k; //將生成的重點加入集合S for(i=0;i<G.vertexNum;i++) //修改陣列dist和path { if(dist[i]>dist[k]+G.arc[k][i]) { dist[i]=dist[k]+G.arc[k][i]; path[i]=path[k]+G.vertex[i]; } } dist[k]=0; //置頂點k 為已生成頂點標記 } } int main(int argc, char** argv) { MGraph G; G.Input(); G.Show(); Dijkastra(G,0); return 0; }