最短路径问题是图论研究中的一个经典算法问题,旨在寻找图(由结点和路径组成的)中两结点之间的最短路径。算法具体的形式包括:
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");
- }
示例:(读者可自行验证)