將全部的頂點分爲兩部分:已知最短路程的頂點集合P和未知最短路徑的頂點集合Q。最開始,已知最短路徑的頂點集合P中只有源點一個頂點。咱們這裏用一個book[ i ]數組來記錄哪些點在集合P中。例如對於某個頂點i,若是book[ i ]爲1則表示這個頂點在集合P中,若是book[ i ]爲0則表示這個頂點在集合Q中。算法
設置源點s到本身的最短路徑爲0即dis=0。若存在源點有能直接到達的頂點i,則把dis[ i ]設爲e[s][ i ]。同時把全部其它(源點不能直接到達的)頂點的最短路徑爲設爲∞。數組
在集合Q的全部頂點中選擇一個離源點s最近的頂點u(即dis[u]最小)加入到集合P。並考察全部以點u爲起點的邊,對每一條邊進行鬆弛操做。例如存在一條從u到v的邊,那麼能夠經過將邊u->v添加到尾部來拓展一條從s到v的路徑,這條路徑的長度是dis[u]+e[u][v]。若是這個值比目前已知的dis[v]的值要小,咱們能夠用新值來替代當前dis[v]中的值。ide
重複第3步,若是集合Q爲空,算法結束。最終dis數組中的值就是源點到全部頂點的最短路徑。優化
完整的Dijkstra算法代碼以下:spa
#include <stdio.h> int main() { int e[10][10],dis[10],book[10],i,j,n,m,t1,t2,t3,u,v,min; int inf=99999999; //用inf(infinity的縮寫)存儲一個咱們認爲的正無窮值 //讀入n和m,n表示頂點個數,m表示邊的條數 scanf("%d %d",&n,&m); //初始化 for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i==j) e[i][j]=0; else e[i][j]=inf; //讀入邊 for(i=1;i<=m;i++) { scanf("%d %d %d",&t1,&t2,&t3); e[t1][t2]=t3; } //初始化dis數組,這裏是1號頂點到其他各個頂點的初始路程 for(i=1;i<=n;i++) dis[i]=e[1][i]; //book數組初始化 for(i=1;i<=n;i++) book[i]=0; book[1]=1; //Dijkstra算法核心語句 for(i=1;i<=n-1;i++) { //找到離1號頂點最近的頂點 min=inf; for(j=1;j<=n;j++) { if(book[j]==0 && dis[j]<min) { min=dis[j]; u=j; } } book[u]=1; for(v=1;v<=n;v++) { if(e[u][v]<inf) { if(dis[v]>dis[u]+e[u][v]) dis[v]=dis[u]+e[u][v]; } } } //輸出最終的結果 for(i=1;i<=n;i++) printf("%d ",dis[i]); getchar(); getchar(); return 0; }
6 9 1 2 1 1 3 12 2 3 9 2 4 3 3 5 5 4 3 4 4 5 13 4 6 15 5 6 4
0 1 8 4 13 17
經過上面的代碼咱們能夠看出,這個算法的時間複雜度是O(N2)。其中每次找到離1號頂點最近的頂點的時間複雜度是O(N),這裏咱們能夠用「堆」(之後再說)來優化,使得這一部分的時間複雜度下降到O(logN)。另外對於邊數M少於N2的稀疏圖來講(咱們把M遠小於N2的圖稱爲稀疏圖,而M相對較大的圖稱爲稠密圖),咱們能夠用鄰接表(這是個神馬東西?不要着急,下週再仔細講解)來代替鄰接矩陣,使得整個時間複雜度優化到O( (M+N)logN )。請注意!在最壞的狀況下M就是N2,這樣的話MlogN要比N2還要大。可是大多數狀況下並不會有那麼多邊,所以(M+N)logN要比N2小不少。blog
歡迎轉載,碼字不容易啊,轉載麻煩註明出處
【啊哈!算法】系列7:Dijkstra最短路算法
http://ahalei.blog.51cto.com/4767671/1387799
ci