最短路徑問題是圖論研究中的一個經典算法問題,旨在尋找圖(由結點和路徑組成的)中兩結點之間的最短路徑。算法具體的形式包括:
1.確定起點的最短路徑問題:即已知起始結點,求最短路徑的問題。適合使用Dijkstra算法。
2.確定終點的最短路徑問題:與確定起點的問題相反,該問題是已知終結結點,求最短路徑的問題。在無向圖中該問題與確定起點的問題完全等同,在有向圖中該問題等同於把所有路徑方向反轉的確定起點的問題。
3.確定起點終點的最短路徑問題:即已知起點和終點,求兩結點之間的最短路徑。
4.全局最短路徑問題:求圖中所有的最短路徑。適合使用Floyd算法。
這裏只給出第1種和第四種情況下兩種算法的源代碼。
- #include "stdio.h"
- #define MAX 99
- typedef struct //圖的鄰接矩陣存儲結構體定義
- {
- int vexs[6];
- int arcs[6][6];
- int n, e;
- }MGraph;
- void create(MGraph &G); //圖的創建
- void Dijkstra(MGraph G, int u); //Dijkstra算法
- void Floyd(MGraph G); //Floyd算法
- int main()
- {
- MGraph G;
- create(G);
- printf("最短路徑之Dijkstra算法:\n");
- Dijkstra(G, 0);
- printf("最短路徑之Floyd算法:\n");
- Floyd(G);
- return 0;
- }
- void create(MGraph &G)
- {
- int i, j;
- printf("請輸入頂點數和邊數:\n");
- scanf("%d %d", &G.n, &G.e);
- int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
- for(i = 0; i < G.n; ++i)
- G.vexs[i] = b[i];
- printf("頂點編號分別爲:\n");
- for(i = 0; i < G.n; ++i)
- printf("%d ", G.vexs[i]);
- int a[6][6]={
- {0, 3, MAX, MAX, MAX, MAX},
- {MAX, 0, 2, MAX, 6, 7},
- {MAX, MAX, 0, 1, 3, 4},
- {MAX, MAX, MAX, 0, 1, MAX},
- {MAX, MAX, MAX, MAX, 0, 1},
- {MAX, MAX, MAX, MAX, MAX, 0}
- };
- for(i = 0; i < 6; ++i)
- for(j = 0; j < 6; ++j)
- G.arcs[i][j]=a[i][j];
- printf("\n該圖的鄰接矩陣:\n");
- for(i = 0; i < G.n; ++i)
- {
- for(j = 0; j < G.n; ++j)
- printf("%d ", G.arcs[i][j]);
- printf("\n");
- }
- }
- //Dijkstra算法
- void Dijkstra(MGraph G, int u) //假設此處從頂點0開始
- {
- int i, j, k, min;
- int pre[10], final[10], dist[10];
- for(j = 0; j < G.n; ++j)
- {
- dist[j] = G.arcs[u][j];
- if(G.arcs[u][j] == MAX)
- pre[j] = -1;
- else
- pre[j] = u;
- final[j] = 0;
- }
- for(i = 1; i < G.n; ++i)
- {
- min = MAX;
- for(j = 1; j < G.n; ++j) //找出最小值的結點
- if( (!final[j]) && (min > dist[j]))
- {
- min = dist[j];
- k = j;
- }
- if(min == MAX) //找不到
- break;
- final[k] = 1; //加入該結點
- for(j = 1; j < G.n; ++j) //更新最短路徑
- {
- if((!final[j]) && (dist[j] > (dist[k] + G.arcs[k][j])))
- {
- dist[j] = dist[k] + G.arcs[k][j];
- pre[j] = k;
- }
- }
- }
- for(i = 1; i < G.n; ++i) //輸出路徑與距離
- {
- if(pre[i] == -1)
- {
- printf("頂點%d到源點%d不可達。\n", i, u);
- continue;
- }
- printf("(%d, %d) = %d\n", i, u, dist[i]);
- printf("路徑爲:");
- j = i;
- while(j)
- {
- printf("%d→", j);
- j = pre[j];
- }
- printf("0\n");
- }
- }
- //Floyd算法
- void Floyd(MGraph G)
- {
- int i, j, k, dist[10][10], pre[10];
- for(i = 0; i < G.n; ++i)
- for(j = 0; j < G.n; ++j)
- {
- dist[i][j] = G.arcs[i][j];
- if(dist[i][j] != MAX)
- pre[j] = i;
- else
- pre[j] = -1;
- }
- for(k = 0; k < G.n; ++k)
- for(i = 0; i < G.n; ++i)
- for(j = 0; j < G.n; ++j)
- if((i != j) && (dist[i][j] > dist[i][k] + dist[k][j]))
- {
- dist[i][j] = dist[i][k] + dist[k][j];
- if(dist[i][j] != MAX)
- {
- pre[j] = k;
- pre[k] = i;
- }
- else
- pre[j] = -1;
- }
- for(i = 0; i < G.n; ++i)
- for(j = 0; j < G.n; ++j)
- {
- if(dist[i][j] == MAX)
- continue;
- else if(i != j)
- printf("(%d, %d) = %d\n", i, j, dist[i][j]);
- }
- printf("其餘頂點之間不可達!\n");
- }
示例:(讀者可自行驗證)