弗洛伊德算法与迪杰斯特拉算法是公认的最著名的两种最短路径求解算法,接下来介绍弗洛伊德算法,弗洛伊德算法的思路是:首先初始化距离矩阵,然后从第一个点开始逐渐更新矩阵点值。d[i][j]表示从i点到j点的距离。第k次更新时,判断d[i][k]+d[k][j]与d[i][j]的大小,如果前者小,则更新这个值,否则不变。
这个算法的核心点在于去往每一个点我们所要尽力的每一个点的记录
(参考图,试着拿本图进行一次构建吧)
通过一个图的权值矩阵求出它的每两点间的最短距离矩阵。
从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。
采用松弛技术(松弛操作),对在i和j之间的所有其他点进行一次松弛。所以时间复杂度为O(n^3);
状态转移方程
其状态转移方程如下: map[i,j]:=min{map[i,k]+map[k,j],map[i,j]};
map[i,j]表示i到j的最短距离,K是穷举i,j的断点,map[n,n]初值应该为0或者自定义的特殊意义的点
参考代码,简化了输入操作直接赋值。
#include <stdio.h> #include <stdlib.h> #define MAXVEX 9 #define INFINITY 65535 struct MGraph { int numVertexes; int *vex; int arc[MAXVEX][MAXVEX]; }; typedef int PathMatrix[MAXVEX][MAXVEX]; typedef int ShortPathTable[MAXVEX][MAXVEX]; void ShortestPath_Floyd(MGraph *G,PathMatrix *P,ShortPathTable *D) { int v,w,k; //初始化 for(v=0; v<G->numVertexes; ++v) { for(w=0; w<G->numVertexes; ++w) { (*D)[v][w]=G->arc[v][w]; (*P)[v][w]=w; } } for(k=0; k<G->numVertexes; ++k) { for(v=0; v<G->numVertexes; ++v) { for(w=0; w<G->numVertexes; ++w) { if( (*D)[v][w]>(*D)[v][k]+(*D)[k][w] ) { // (v到w的距离) VS (v到k的距离+k到w的距离) (*D)[v][w]=(*D)[v][k]+(*D)[k][w]; (*P)[v][w]=(*P)[v][k]; //若从v出发,要去w,则先要从v去到k,“再作下一步打算(下一步即(*P)[k][w])” } } } } } void main() { MGraph *my_g=(struct MGraph*)malloc(sizeof(struct MGraph)); int i,j; int t=0; int v0=0; int vv=8; my_g->numVertexes=MAXVEX; my_g->vex=(int*)malloc(sizeof(char)*my_g->numVertexes); if(!my_g->vex) return; for(i=0; i<my_g->numVertexes; ++i) //一维数组(图中各结点)初始化{0,1,2,3,4,5,6,7,8} my_g->vex[i]=i++; for(i=0; i<my_g->numVertexes; ++i) for(j=0; j<my_g->numVertexes; ++j) my_g->arc[i][j]=INFINITY; // 无向图的权值二维数组为对称矩阵 my_g->arc[0][1]=1; my_g->arc[0][2]=5; my_g->arc[1][2]=3; my_g->arc[1][3]=7; my_g->arc[1][4]=5; my_g->arc[2][4]=1; my_g->arc[2][5]=7; my_g->arc[3][4]=2; my_g->arc[3][6]=3; my_g->arc[4][5]=3; my_g->arc[4][6]=6; my_g->arc[4][7]=9; my_g->arc[5][7]=5; my_g->arc[6][7]=2; my_g->arc[6][8]=7; my_g->arc[7][8]=4; for(i=0; i<my_g->numVertexes; ++i) for(j=0; j<=i; ++j) { if(i==j) { my_g->arc[i][j]=0; continue; } my_g->arc[i][j]=my_g->arc[j][i]; } for(i=0; i<my_g->numVertexes; ++i) { //二维数组表示图中各结点间连接边的weight for(j=0; j<my_g->numVertexes; ++j) printf("%5d ",my_g->arc[i][j]); printf("\n"); } printf("\n\n"); PathMatrix D; ShortPathTable P; ShortestPath_Floyd(my_g,&P,&D); for(i=0; i<MAXVEX; ++i) { //二维数组表示图中各结点间连接边的weight for(j=0; j<MAXVEX; ++j) printf("%5d ",P[i][j]); printf("\n"); } printf("\n\n"); free(my_g->vex); }
本文固定URL:https://www.dotcpp.com/course/153
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程