Dijkstra演算法(一個節點到其他所有節點的最短路徑)
阿新 • • 發佈:2018-12-30
Dijkstra(迪傑斯特拉)演算法是典型的單源最短路徑演算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。Dijkstra演算法是很有代表性的最短路徑演算法,在很多專業課程中都作為基本內容有詳細的介紹,如資料結構,圖論,運籌學等等。注意該演算法要求圖中不存在負權邊。
問題描述:在無向圖 G=(V,E) 中,假設每條邊 E[i] 的長度為 w[i],找到由頂點 V0 到其餘各點的最短路徑。(單源最短路徑)
演算法思想:設G=(V,E)是一個帶權有向圖,把圖中頂點集合V分成兩組,第一組為已求出最短路徑的頂點集合(用S表示,初始時S中只有一個源點,以後每求得一條最短路徑 , 就將加入到集合S中,直到全部頂點都加入到S中,演算法就結束了),第二組為其餘未確定最短路徑的頂點集合(用U表示),
演算法步驟:
a.初始時,S只包含源點,即S={v},v的距離為0。U包含除v外的其他頂點,即:U={其餘頂點},若v與U中頂點u有邊,則<u,v>正常有權值,若u不是v的出邊鄰接點,則<u,v>權值為∞。
b.從U中選取一個距離v最小的頂點k,把k,加入S中(該選定的距離就是v到k的最短路徑長度)。
c.以k為新考慮的中間點,修改U中各頂點的距離;若從源點v到頂點u的距離(經過頂點k)比原來距離(不經過頂點k)短,則修改頂點u的距離值,修改後的距離值的頂點k的距離加上邊上的權。
d.重複步驟b和c直到所有頂點都包含在S中。
說來慚愧,雖然上學期就學了資料結構,今天卻是第一次寫Dijkstra演算法,為了理解方便,註釋也照著書敲了一遍。#include <stdio.h> #include <stdlib.h> #define MAXV 100 #define INF 999999 typedef struct{ int edges[MAXV][MAXV];//鄰接矩陣的邊陣列 int n,e;//頂點數,邊數 }MGraph;//完整的圖鄰接矩陣型別 void Dispath(MGraph g,int dist[],int path[],int s[],int v); void Dijkstra(MGraph g,int v) { int dist[MAXV];//dist[i]儲存從源點到i的目前的最短路徑長度 int path[MAXV];//path[i]儲存當前最短路徑中的前一個頂點的編號 int s[MAXV];//標記已找到最短路徑的頂點,s[i]=0表示未找到,s[i]=1表示已找到。 int mindis,i,j,u; for(i=0;i<g.n;i++) { dist[i]=g.edges[v][i];//距離初始化 s[i]=0;//s[ ]置空 if(g.edges[v][i]<INF)//路徑初始化 path[i]=v;//頂點v到頂點i有邊時,置頂點i的前一個頂點為v else path[i]=-1;//頂點v到頂點i沒有邊時,置頂點i的前一個頂點為-1 } s[v]=1;//源點編號v放入s中 path[v]=0; for(i=0;i<g.n;i++)//迴圈直到所有頂點的最短路徑都求出 { mindis=INF;//mindis置最小長度初值為無窮大 u=-1; for(j=0;j<g.n;j++) if(s[j]==0&&dist[j]<mindis)//選取不在s[]中且具有最小距離的頂點u { u=j; mindis=dist[j]; } s[u]=1;//頂點u加入s for(j=0;j<g.n;j++)//修改不在s中的頂點的距離 if(s[j]==0) if(g.edges[u][j]<INF&&dist[u]+g.edges[u][j]<dist[j]) { dist[j]=dist[u]+g.edges[u][j]; path[j]=u; } } Dispath(g,dist,path,s,v); } void Dispath(MGraph g,int dist[],int path[],int s[],int v) { int i,j,k; int apath[MAXV],d;//存放一條最短路徑(逆向)及其頂點個數 for(i=0;i<g.n;i++) if(s[i]==1&&i!=v) { printf("從頂點%d到頂點%d的路徑長度為:%d\t路徑為:",v,i,dist[i]); d=0,apath[d]=i;//新增路徑上的終點 k=path[i]; if(k==-1)//沒有路徑的情況 printf("無路徑\n"); else//存在路徑時輸出該路徑 { while(k!=v) { d++; apath[d]=k; k=path[k]; } d++; apath[d]=v;//新增路徑上的起點 printf(" %d",apath[d]);//先輸出起點 for(j=d-1;j>=0;j--)//再輸出其他頂點 printf(",%d",apath[j]); printf("\n"); } } } void DispMat(MGraph g) //輸出鄰接矩陣g { int i,j; for (i=0;i<g.n;i++) { for (j=0;j<g.n;j++) if (g.edges[i][j]==INF) printf("%3s","∞"); else printf("%3d",g.edges[i][j]); printf("\n"); } } int main() { int i,j,u=0; MGraph g; int A[MAXV][6]={ {0,5,INF,7,INF,INF}, {INF,0,4,INF,INF,INF}, {8,INF,0,INF,INF,9}, {INF,INF,5,0,INF,6}, {INF,INF,INF,5,0,INF}, {3,INF,INF,INF,1,0}}; g.n=6;g.e=10; for(i=0;i<g.n;i++) for (j=0;j<g.n;j++) g.edges[i][j]=A[i][j]; printf("有向圖G的鄰接矩陣:\n"); DispMat(g); Dijkstra(g,u); printf("\n"); }
原諒我只會用畫圖工具畫圖,有大佬可以告訴我下比較好用的畫這種圖的工具。