图->最短路径->多源最短路径(弗洛伊德算法Floyd)

文字描述

  求每一对顶点间的最短路径,可以每次以一个顶点为源点,重复执行迪杰斯特拉算法n次。这样,便可求得每一对顶点之间的最短路径。总的执行时间为n^3。但是还有另外一种求每一对顶点间最短路径的方法,就是弗洛伊德(Floyd)算法,它的时间复杂度也为n^3,但是形式上更简单,其基本思想如下:

  

  如果无法理解上面的文字的话,建议看下代码实现部分,可以更容易理解。

 

示意图

 

 

算法分析

时间复杂度为n^3

 

代码实现

  1 //
  2 // Created by lady on 19-1-6.
  3 //
  4 
  5 #include <stdlib.h>
  6 #include <stdio.h>
  7 #include <string.h>
  8 
  9 #define INFINITY        100000    //最大值
 10 #define MAX_VERTEX_NUM    20        //最大顶点数
 11 
 12 typedef enum {DG, DN, UDG, UDN} GraphKind; //{有向图,有向网,无向图,无向网}
 13 typedef struct ArcCell{
 14     int weight;    //该弧相关信息的指针
 15 }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM], PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
 16 typedef struct VertexType{
 17     char data[10];
 18 }VertexType;
 19 typedef struct{
 20     VertexType vexs[MAX_VERTEX_NUM];    //顶点向量
 21     AdjMatrix arcs;        //邻接矩阵
 22     int vexnum, arcnum;    //图的当前顶点数和弧数
 23     GraphKind kind;        //图的种类标志
 24 }MGraph;
 25 
 26 /*
 27  * 根据顶点信息, 返回该顶点在图中的位置, 如果返回-1表示顶点不存在
 28  */
 29 static int LocateVex(MGraph *G, char data[])
 30 {
 31     int i = 0;
 32     for(i=0; i<G->vexnum; i++){
 33         if(!strncmp(G->vexs[i].data, data, strlen(G->vexs[i].data))){
 34             return i;
 35         }
 36     }
 37     return -1;
 38 }
 39 
 40 /*
 41  * 用邻接矩阵作为存储结构,创建有向网
 42  */
 43 static int CreateGraphDN(MGraph *G)
 44 {
 45     printf("用邻接矩阵创建有向网,输入顶点数,弧数:");
 46     G->kind = DN;
 47     scanf("%d,%d", &G->vexnum, &G->arcnum);
 48     if(G->vexnum > MAX_VERTEX_NUM){
 49         printf("错误:顶点数不能超过%d!!\n", MAX_VERTEX_NUM);
 50         return -1;
 51     }
 52     int i = 0, j = 0, k = 0;
 53     char v1[10] = {0}, v2[10]={0}, info[10] = {0};
 54     char tmp[30] = {0};
 55     for(i=0; i<G->vexnum; i++){
 56         printf("输入第%d个顶点: ", i);
 57         memset(G->vexs[i].data, 0, sizeof(G->vexs[0].data));
 58         scanf("%s", G->vexs[i].data);
 59         for(j=0; j<G->vexnum; j++){
 60             G->arcs[i][j].weight = INFINITY;
 61         }
 62         G->arcs[i][i].weight = 0;
 63     }
 64     for(k=0; k<G->arcnum; k++){
 65         printf("输入第%d条弧(顶点1, 顶点2, 权值): ", k);
 66         memset(tmp, 0, sizeof(tmp));
 67         scanf("%s", tmp);
 68         sscanf(tmp, "%[^','],%[^','],%s[^\\n]", v1, v2, info);
 69         i = LocateVex(G, v1);
 70         j = LocateVex(G, v2);
 71         if(i<0 || j<0 || (!atoi(info))){
 72             printf("错误:顶点%s或者%s不存在, 或者权值信息%s不对!\n", v1, v2, info);
 73             return -1;
 74         }
 75         G->arcs[i][j].weight = atoi(info);
 76     }
 77     return 0;
 78 }
 79 
 80 
 81 static void printMatrix(int vexnum, VertexType vexs[], int (*arcs)[MAX_VERTEX_NUM])
 82 {
 83     int i = 0, j = 0;
 84     printf("\t");
 85     for(i=0; i<vexnum; i++){
 86         printf("%s\t", vexs[i].data);
 87     }
 88     printf("\n");
 89     for(i=0; i<vexnum; i++){
 90         printf("%s\t", vexs[i].data);
 91         for(j=0; j<vexnum; j++){
 92             if(arcs[i][j] == INFINITY){
 93                 printf("INF\t");
 94             }else{
 95                 printf("%d\t", arcs[i][j]);
 96             }
 97         }
 98         printf("\n");
 99     }
100     return ;
101 }
102 static void printArchs(int vexnum, VertexType vexs[], AdjMatrix arcs)
103 {
104     int i = 0, j = 0;
105     printf("\t");
106     for(i=0; i<vexnum; i++){
107         printf("%s\t", vexs[i].data);
108     }
109     printf("\n");
110     for(i=0; i<vexnum; i++){
111         printf("%s\t", vexs[i].data);
112         for(j=0; j<vexnum; j++){
113             if(arcs[i][j].weight == INFINITY){
114                 printf("INF\t");
115             }else{
116                 printf("%d\t", arcs[i][j].weight);
117             }
118         }
119         printf("\n");
120     }
121     return ;
122 }
123 
124 /*
125  * 用Floyd算法求有向图G中各顶点v和w之间的最短路径P[v][w]及其
126  * 带权长度D[v][w]。若P[v][w][u]为1, 则u为从v到w当前求得最短路径上的顶点。
127  */
128 void ShortestPath_Floyd(MGraph *G)
129 {
130     int u=0, v=0, w=0;
131     int i=0, j=0;
132     int P[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM];
133     int D[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
134     //各对结点之间初始已知路径和距离
135     for(v=0; v<G->vexnum; v++){
136         for(w=0; w<G->vexnum; w++){
137             D[v][w] = G->arcs[v][w].weight;
138             for(u=0; u<G->vexnum; u++){
139                 P[v][w][u] = 0;
140             }
141             //从v到w有直接路径
142             if(D[v][w] < INFINITY){
143                 P[v][w][v] = 1;
144                 P[v][w][w] = 1;
145             }
146         }
147     }
148 
149     for(u=0; u<G->vexnum; u++){
150         for(v=0; v<G->vexnum; v++){
151             for(w=0; w<G->vexnum; w++){
152                 if( D[v][u]+D[u][w] < D[v][w]){
153                     //从v经u到w的一条路径更短。
154                     D[v][w] = D[v][u] + D[u][w];
155                     for(i=0; i<G->vexnum; i++){
156                         P[v][w][i] = (P[v][u][i] || P[u][w][i]) ? 1: 0;
157                     }
158                 }
159             }
160         }
161     }
162 
163     printf("\n打印各个顶点间的最短路径的权值:\n");
164     printMatrix(G->vexnum, G->vexs, D);
165 
166     printf("\n打印各个顶点间的最短路径的中间结点:\n");
167     for(u=0; u<G->vexnum; u++){
168         for(v=0; v<G->vexnum; v++){
169             printf("minpath(%d,%s<->%d,%s):", u, G->vexs[u].data, v, G->vexs[v].data);
170             for(w=0; w<G->vexnum; w++){
171                 if(P[u][v][w] && (u!=v)){
172                     printf("%s\t", G->vexs[w].data);
173                 }
174             }
175             printf("\n");
176         }
177     }
178 
179     return 0;
180 }
181 
182 int main(int argc, int *argv[])
183 {
184     //以邻接矩阵为存储结构创建有向网
185     MGraph G;
186     if(CreateGraphDN(&G) < 0){
187         return -1;
188     }
189     printf("\n打印该图中的信息:\n");
190     printArchs(G.vexnum, G.vexs, G.arcs);
191     //Floyd弗洛依德算法求多源最短路径
192     ShortestPath_Floyd(&G);
193 }
弗洛依德算法(Floyd)求多源最短路径

 

代码运行

 

/home/lady/CLionProjects/untitled/cmake-build-debug/untitled
用邻接矩阵创建有向网,输入顶点数,弧数:3,5
输入第0个顶点: A
输入第1个顶点: B
输入第2个顶点: C
输入第0条弧(顶点1, 顶点2, 权值): A,B,4
输入第1条弧(顶点1, 顶点2, 权值): B,A,6
输入第2条弧(顶点1, 顶点2, 权值): A,C,11
输入第3条弧(顶点1, 顶点2, 权值): C,A,3
输入第4条弧(顶点1, 顶点2, 权值): B,C,2

打印该图中的信息:
    A    B    C    
A    0    4    11    
B    6    0    2    
C    3    INF    0    

打印各个顶点间的最短路径的权值:
    A    B    C    
A    0    4    6    
B    5    0    2    
C    3    7    0    

打印各个顶点间的最短路径的中间结点:
minpath(0,A<->0,A):
minpath(0,A<->1,B):A    B    
minpath(0,A<->2,C):A    B    C    
minpath(1,B<->0,A):A    B    C    
minpath(1,B<->1,B):
minpath(1,B<->2,C):B    C    
minpath(2,C<->0,A):A    C    
minpath(2,C<->1,B):A    B    C    
minpath(2,C<->2,C):

Process finished with exit code 0

 

posted on 2019-01-06 18:05  LiveWithACat  阅读(408)  评论(0编辑  收藏  举报