图->最短路径->多源最短路径(弗洛伊德算法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 }
代码运行
/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) 编辑 收藏 举报