Dijkstra算法是在圖中尋找兩頂點最短路徑的算法。
下面以下圖有向圖為例,說明其基本思想。
上圖為轉化為鄰接矩陣存儲:
現在我要尋找1點到其他點的最短距離以及路徑:
a)1點到各點的距離分別為: 0 1 12 無窮 無窮 無窮
b)從上述距離中尋找最小的距離,發現距離2點最近,那么選擇2點作為“跳板”
c) 1以2作跳板后到各個點的距離分別為(即必走1->2) : 0 1 10 4 無窮 無窮
往后的工作就是重復b) c)繼續找最短的距離作為跳板,直到各個點都做過跳板為止。 那么最終這6個數字分別就是頂點1到各個點的最短距離。
有幾個問題需要注意:
1. 步驟a)b)找到跳板后再得到c),需要改變的值只是以跳板做中間量后距離變短的值,比如說上述黃色兩個部分的第三個位置,加了跳板后是10<沒加跳板的12,這時候才需要改成10。假設加了跳板后的值反而比沒加前變大了,那么保留原來的值。(這就是的dijkstra的“貪心算法”)。
2. 找跳板的時候只能從沒做過跳板中的元素中取。
3.上述方法僅僅講述了如何求得最短距離,並沒有提最短路徑,最短路徑的實現方法將在過幾天的代碼中體現。
以下代碼以圖:
// Dijkstra.cpp : 定義控制台應用程序的入口點。 // #include "stdafx.h" #include "stdlib.h" #define M 999999
int a[7][7]={0,0,0,0,0,0,0, 0,0,50,10,M,45,M, 0,M,0,15,M,10,M, 0,20,M,0,15,M,M, 0,M,20,M,0,30,M, 0,M,M,M,35,0,M, 0,M,M,M,3,M,0 }; int book[10]; int dis[10]; int i,j,k,u,min; void dijsktra() { for(i=1;i<=6;i++) { dis[i]=a[1][i]; book[i]=0; } book[1]=1; //1點的初始化 for(i=2;i<=6;i++) { min=M; for(j=2;j<=6;j++) { if(book[j]==0&&dis[j]<min) //找當前最小距離 {min=dis[j]; u=j; } } book[u]=1; for(k=1;k<=6;k++) //若跳板距離更短,那么選擇跳板距離作為最短距離 即注1 { if((dis[k])>(a[u][k]+dis[u])&&(a[u][k]<M)) //單獨注意a[u][k],表示以u點做跳板,跳板到k的距離 巧妙利用了鄰接表 dis[k]=dis[u]+a[u][k]; } } for(i=1;i<=6;i++) { printf("%d ",dis[i]); } } int _tmain(int argc, _TCHAR* argv[]) { printf(" \n"); dijsktra(); system("pause"); return 0; }
未完待續,有路徑輸出的在加着注釋 。
參考資料:
https://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html
http://lobert.iteye.com/blog/2315820
