单源最短路径之迪杰斯特拉算法(C语言)
生活随笔
收集整理的這篇文章主要介紹了
单源最短路径之迪杰斯特拉算法(C语言)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Dijkstra(迪杰斯特拉)算法
采用廣度優先搜索思想,對有向賦權圖尋找最短路徑。
該算法對于不含負權的有向圖來說,是目前已知的最快的單源最短路徑算法。
時間復雜度:O(n^2)
基本原理:不斷為為每個頂點 v 保留目前為止所找到的從s到v的最短路徑
上圖為戴克斯特拉算法應用示意圖。
起點以左下角的紅點,目標是右上角的綠點,中間灰色的倒L型為障礙物。藍色空圈表示”暫定”,用以搜索下一步;已經填充顏色的表示探訪過,圖中顏色以紅到綠,越綠表示離起點越遠。所有節點都被均勻的探索。
我們以下圖為例:
假設以“1”為頂點出發,求解到每個頂點的最短路徑,若可達,則輸出最短路徑;若不可達,則輸出無窮大(32767)
shortest(1, 2)=2
shortest(1, 3)=4
shortest(1, 4)=5
注:經對比,第二種路徑得到的權值和較小,取第二種方式
shortest(1, 5)=2
算法如下:
void dijkstra(AdjMatrix *G) {int i,j;int min,minid;int tmp;int vs;int prev[MAX] = {0};int dist[MAX] = {0};int visited[MAX]; // visited[i]=1表示"頂點vs"到"頂點i"的最短路徑已成功獲取。// 初始化printf("請輸入要查詢的單源頂點");scanf("%d",&vs);vs-=1;for (i = 0; i < G->numV; i++){visited[i] = 0; // 頂點i的最短路徑還沒獲取到。prev[i] = 0; // 頂點i的前驅頂點為0。dist[i] = G->Edge[vs][i];// 頂點i的最短路徑為"頂點vs"到"頂點i"的權。}// 對"頂點vs"進行初始化visited[vs] = 1;//將頂點vs加入最短路徑,對應的visited[i]置為1 dist[vs] = 0;//到自己的權為0 // 遍歷G.vexnum-1次;每次找出一個頂點的最短路徑。for (i = 1; i < G->numV; i++){// 尋找當前最小的路徑;// 即,在未獲取最短路徑的頂點中,找到離vs最近的頂點(minid)。min = INF;for (j = 0; j < G->numV; j++){if (visited[j]==0 && dist[j]<min){min = dist[j];minid = j;}}visited[minid] = 1;// 標記"頂點minid"為已經獲取到最短路徑// 更新當前最短路徑和前驅頂點// 即,當已經"頂點minid的最短路徑"之后,更新"未獲取最短路徑的頂點的最短路徑和前驅頂點"。for (j = 0; j < G->numV; j++){tmp = (G->Edge[minid][j]==INF ? INF : (min + G->Edge[minid][j]));// 防止溢出 if (visited[j] == 0 && (tmp < dist[j]) ){dist[j] = tmp;prev[j] = minid;}}}// 打印dijkstra最短路徑的結果printf("dijkstra(%c): \n", G->Vertices[vs]);for (i = 0; i < G->numV; i++)printf(" shortest(%c, %c)=%d\n", G->Vertices[vs], G->Vertices[i], dist[i]); }具體代碼如下:
#include<stdio.h> #include<stdlib.h> #define MaxVertices 100 //假設包含100個頂點 #define MaxWeight 32767 //不鄰接時為32767,但輸出時用 "∞" #define MAX 100 #define INF (~(0x1<<31)) typedef struct{ //包含權的鄰接矩陣的的定義char Vertices[MaxVertices]; //頂點信息的數組int Edge[MaxVertices][MaxVertices]; //邊的權信息的數組int numV; //當前的頂點數int numE; //當前的邊數 }AdjMatrix;void CreateGraph(AdjMatrix *G) //圖的生成函數 { int n,e,vi,vj,w,i,j;printf("請輸入圖的頂點數和邊數(以空格分隔):");scanf("%d%d",&n,&e);G->numV=n;G->numE=e;for(i=0;i<n;i++) //圖的初始化for(j=0;j<n;j++){ if(i==j)G->Edge[i][j]=0;else G->Edge[i][j]=32767;}for(i=0;i<n;i++)for(i=0;i<G->numV;i++) //將頂點存入數組中{ printf("請輸入第%d個頂點的信息(整型):",i+1); // G->adjlist[i].vertex=getchar(); scanf(" %c",&G->Vertices[i]);}printf("\n");for(i=0;i<G->numE;i++){ printf("請輸入邊的信息i,j,w(以空格分隔):");scanf("%d%d%d",&vi,&vj,&w); //若為不帶權值的圖,則w輸入1//若為帶權值的圖,則w輸入對應權值G->Edge[vi-1][vj-1]=w;//①//G->Edge[vj-1][vi-1]=w;//②//無向圖具有對稱性的規律,通過①②實現//有向圖不具備此性質,所以只需要①} } void DispGraph(AdjMatrix G) //輸出鄰接矩陣的信息 { int i,j;printf("\n輸出頂點的信息(整型):\n");for(i=0;i<G.numV;i++)printf("%8c",G.Vertices[i]);printf("\n輸出鄰接矩陣:\n");printf("\t");for(i=0;i<G.numV;i++)printf("%8c",G.Vertices[i]);for(i=0;i<G.numV;i++){ printf("\n%8d",i+1);for(j=0;j<G.numV;j++){ if(G.Edge[i][j]==32767) //兩點之間無連接時權值為默認的32767,但輸出時為了方便輸出 "∞"printf("%8s", "∞");elseprintf("%8d",G.Edge[i][j]);}printf("\n"); } } void dijkstra(AdjMatrix *G) {int i,j;int min,minid;int tmp;int vs;int prev[MAX] = {0};int dist[MAX] = {0};int visited[MAX]; // visited[i]=1表示"頂點vs"到"頂點i"的最短路徑已成功獲取。// 初始化printf("請輸入要查詢的單源頂點");scanf("%d",&vs);vs-=1;for (i = 0; i < G->numV; i++){visited[i] = 0; // 頂點i的最短路徑還沒獲取到。prev[i] = 0; // 頂點i的前驅頂點為0。dist[i] = G->Edge[vs][i];// 頂點i的最短路徑為"頂點vs"到"頂點i"的權。}// 對"頂點vs"進行初始化visited[vs] = 1;//將頂點vs加入最短路徑,對應的visited[i]置為1 dist[vs] = 0;//到自己的權為0 // 遍歷G.vexnum-1次;每次找出一個頂點的最短路徑。for (i = 1; i < G->numV; i++){// 尋找當前最小的路徑;// 即,在未獲取最短路徑的頂點中,找到離vs最近的頂點(minid)。min = INF;for (j = 0; j < G->numV; j++){if (visited[j]==0 && dist[j]<min){min = dist[j];minid = j;}}visited[minid] = 1;// 標記"頂點minid"為已經獲取到最短路徑// 更新當前最短路徑和前驅頂點// 即,當已經"頂點minid的最短路徑"之后,更新"未獲取最短路徑的頂點的最短路徑和前驅頂點"。for (j = 0; j < G->numV; j++){tmp = (G->Edge[minid][j]==INF ? INF : (min + G->Edge[minid][j]));// 防止溢出 if (visited[j] == 0 && (tmp < dist[j]) ){dist[j] = tmp;prev[j] = minid;}}}// 打印dijkstra最短路徑的結果printf("dijkstra(%c): \n", G->Vertices[vs]);for (i = 0; i < G->numV; i++)printf(" shortest(%c, %c)=%d\n", G->Vertices[vs], G->Vertices[i], dist[i]); } int main() { AdjMatrix G;freopen("1.txt","r",stdin);CreateGraph(&G);dijkstra(&G);DispGraph(G);}注:該算法是在鄰接矩陣的基礎上完成的,請參照鄰接矩陣(C語言)
注:由于測試輸入數據較多,程序可以采用文件輸入
5 7
1
2
3
4
5
1 2 2
1 3 4
1 5 2
2 3 1
2 4 6
3 4 2
4 5 3
2
總結
以上是生活随笔為你收集整理的单源最短路径之迪杰斯特拉算法(C语言)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL_日期时间处理函数及应用
- 下一篇: 基于YARN集群构建运行PySpark