数据结构——图——弗洛伊德(Floyd)算法
数据结构——图——弗洛伊德(Floyd)算法
为了能讲明白弗洛伊德(Flbyd)算法的精妙所在,我们先来看最简单的案例。图7-7-12的左图是一个最简单的3个顶点连通网图。
我们先定义两个二维数组D[3][3]和P[3][3],D代表顶点到顶点的最短路径权值和的矩阵。P代表对应顶点的最小路径的前驱矩阵。在未分析任何顶点之前,我们将D命名为D-1,其实它就是初始的图的邻接矩阵。将Р命名为P-1,初始化为图中所示的矩阵。
首先我们来分析,所有的顶点经过V0后到达另一顶点的最短路径。因为只有三个顶点,因此需要查看V1→V0→V2,得到D-1[1][0]+D-1 [0][2]=2+1=3。D-1[1][2]表示的是V1→V2的权值为5,我们发现D-1[1][2]>D-1[1][0]+D-1 [0][2],通俗的话讲就是V1→V0→V2比直接V1→V2距离还要近。所以我们就让D-1[1][2]= D-1[1][0]+D-1[0][2]=3,同样的D-1[2][1]=3,于是就有了D-0的矩阵。因为有变化,所以Р矩阵对应的P-1[1][2]和P-1[2][1]也修改为当前中转的顶点V0的下标0,于是就有了P。也就是说
接下来,其实也就是在D-0和P-0的基础上继续处理所有顶点经过V1和V2后到达另一顶点的最短路径,得到D-1和P-1、D-2和P-2完成所有顶点到所有顶点的最短路径计算工作。
如果我就用这么简单的图形来讲解代码,大家一定会觉得不能说明什么问题。所以我们还是以前面的复杂网图为例,来讲解弗洛伊德(Flbyd)算法。
首先我们针对图7-7-13的左网图准备两个矩阵D-1和P-1,D-1就是网图的邻接矩阵,P-1初设为P[i][们]=j这样的矩阵,它主要用来存储路径。
代码如下,注意因为是求所有顶点到所有顶点的最短路径,因此 Pathmatirx和ShortPathTable都是二维数组。
typedef struct
{VertexType vexs[MAXVEX]; /*顶点表*/EdgeType matirx[MAXVEX][MAXVEX]; /*领边矩阵,可看作边表*/int numVertexes, numEdges; /*图中当前的顶点数和边数*/
} MGraph;typedef int Pathmatirx[MAXVEX][MAXVEX]; /*用于存储最短路径下标的数组*/
typedef int ShortPathTable[MAXVEX][MAXVEX]; /*用于存储到各点最短路径的权值和*/
/*Floyd算法,求网图G中各顶点V到其余顶点w最短路径p[v][w]及带权长度D[v][w]*/
void ShortestPath_Floyd(MGraph G, Pathmatirx* 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.matirx[v][w]; /*(*D)[v][w]值即为对应点间的权值*/(*P)[v][w] = w; /*初始化P*/}}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]){/*如果经过下标为K顶点路径比原点间路径更短*//*将当前两点间权值设为更小的一个*/(*D)[v][w] = (*D)[v][k] + (*D)[k][w];(*P)[v][w] = (*P)[v][k];/*路径设置经过下标为k的顶点*/}}}}
}
1.程序开始运行,第4~11行就是初始化了D和P,使得它们成为图7-7-13的两个矩阵。从矩阵也得到,V0→V1路径权值是1,V0→V2路径权值是5,V0→V3无边连线,所以路径权值为极大值65535。
2.第12~25行,是算法的主循环,一共三层嵌套,k 代表的就是中转顶点的下标。v代表起始顶点,w代表结束顶点。
3.当 K=0时,也就是所有的顶点都经过V0中转,计算是否有最短路径的变化。可惜结果是,没有任何变化,如图7-7-14所示。
4.当K=1 时,也就是所有的顶点都经过V1中转。此时,当 V=0时,原本D[0][2]=5,现在由于 D[0][1]+D[1][2]=4。因此由代码的第20行,二者取其最小值,得到 D[0][2]=4,同理可得 D[0][3]=8、D[0][4]=6,当v=2、3、4时,也修改了一些数据,请参考如图7-7-15左图中虚线框数据。由于这些最
小权值的修正,所以在路径矩阵P上,也要作处理,将它们都改为当前的P[v][k]值,见代码第21行。
5.接下来就是 k=2一直到8结束,表示针对每个顶点做中转得到的计算结果,当然,我们也要清楚,D-0是以D-1为基础,D-1是以D-0为基础,……,D-8是以D-7为基础,就像我们曾经说过的七个包子的故事,它们是有联系的,路径矩阵Р也是如此。最终当k=8时,两矩阵数据如图7-7-16所示。
至此,我们的最短路径就算是完成了,你可以看到矩阵第vo行的数值与迪杰斯特拉(Dijkstra)算法求得的D数组的数值是完全相同,都是{0,1,4,7,5,8,10,12,16}。而且这里是所有顶点到所有顶点的最短路径权值和都可以计算出。
那么如何由P这个路径数组得出具体的最短路径呢?以V0到V8为例,从图7-7-16的右图第V8列,P[0][8]=1,得到要经过顶点V1,然后将1取代0得到P[1][8]=2,说明要经过V2,然后将2取代1得到P[2][8]=4,说明要经过V4,然后将4取代2得到P[4][8]=3,说明要经过V3,……,这样很容易就推导出最终的最短路径值为V0→V1→V2→V4→V3→V6→V7→V8
求最短路径的显示代码可以这样写。
for ( v = 0; v < G.numVertexes; ++v){for (w = v+1; w < G.numVertexes; w++){printf("v%d-v%d weight: %d", v, w, D[v][w]);k = P[v][w]; /*获得第一个路径顶点下标*/printf("path:%d",v); /*打印源点*/while (k!=w) /*如果路径顶点下标不是终点*/{printf("->%d", k); /*打印路径顶点*/k = P[k][w]; /*获得下一个路径顶点下标*/}printf("-> %d\n", w); /*打印终点*/}printf("\n");}
再次回过头来看看弗洛伊德 (Flbyd)算法,它的代码简洁到就是一个二重循环初始化加一个三重循环权值修正,就完成了所有顶点到所有顶点的最短路径计算。几乎就如同是我们在学习C语言循环嵌套的样例代码而已。如此简单的实现,真是巧妙之极,在我看来,这是非常漂亮的算法,不知道你们是否喜欢?很可惜由于它的三重循环,因此也是 O(n3)时间复杂度。如果你面临需要求所有顶点至所有顶点的最短路径问题时,弗洛伊德(Floyd)算法应该是不错的选择。
另外,我们虽然对求最短路径的两个算法举例都是无向图,但它们对有向图依然有效,因为二者的差异仅仅是邻接矩阵是否对称而已。
数据结构——图——弗洛伊德(Floyd)算法相关推荐
- 数据结构与算法(7-4)最短路径(迪杰斯特拉(Dijkstra)算法、弗洛伊德(Floyd)算法)
目录 一.最短路径概念 二.迪杰斯特拉(Dijkstra)算法(单源最短路径) 1.原理 2.过程 3.代码 三.弗洛伊德(Floyd)算法(多源最短路径) 1.原理 2.存储 3.遍历 4.代码 参 ...
- 算法其实很简单—弗洛伊德(Floyd)算法
目录 1.弗洛伊德(Floyd)算法介绍 2.弗洛伊德(Floyd)算法最佳应用-最短路径 3.弗洛伊德(Floyd)算法图解分析 3.1 弗洛伊德算法的步骤: 4.代码实现 1.弗洛伊德(Floyd ...
- Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法
1.Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法 1.1 迪杰斯特拉(Dijkstra)算法 1.1.1 迪杰斯特拉(Dijkstra)算法介绍 迪杰斯特拉(Dijkstra ...
- 060.弗洛伊德(Floyd)算法的原理以及解决最短路径问题
1. 弗洛伊德(Floyd)算法的原理 1.1. 基本介绍 1.1.1. 弗洛伊德算法和迪杰斯特拉算法比较 1.2. 算法步骤 1.3. 步骤图解 1.3.1. 第一轮循环 1.3.2. 找出每个点作 ...
- Java实现之弗洛伊德(Floyd)算法
一.问题引入 1.问题引入 1)胜利乡有7个村庄(A,B,C,D,E,F, G) 2)各个村庄的距离用边线表示(权),比如A-B距离5公里3)问:如何计算出各村庄到其它各村庄的最短距离? 二.基本介绍 ...
- 弗洛伊德(Floyd)算法求解图的最短路径
弗洛伊德(Froyd)算法用于求解所有顶点到所有顶点的的最短路径.时间复杂度为O(n^3). 正如我们所知道的,Floyd算法用于求最短路径.Floyd算法可以说是Warshall算法的扩展,三个fo ...
- 【数据结构笔记24】单源最短路(迪克斯拉Dijkstra算法),多源最短路(弗洛伊德Floyd算法)
本次笔记内容: 7.1.1 概述 7.1.2 无权图的单源最短路 7.1.3 有权图的单源最短路 7.1.3-s 有权图的单源最短路示例 7.1.4 多源最短路算法 文章目录 最短路径问题 最短路径问 ...
- 货币套汇(图路径)-- 数据结构 (深搜+Floyd算法)
深搜+Floyd算法 深搜 Floyd算法 题目描述 套汇是指利用货币汇兑率的差异将一个单位的某种货币转换为大于一个单位的同种货币. 例如,假定1 美元可以买0.7 英镑,1 英镑可以买9.5法郎,1 ...
- 数据结构——图——最短路径DF算法
一.Dijkstra算法(贪心地求最短距离的算法) 在此算法中,我按照自己的理解去命名,理解起来会轻松一些. #define MAXSIZE 100 #define UNVISITED 0 #defi ...
最新文章
- Python:urllib2模块的基本使用
- Lossless Codec---APE代码解读系列(二)
- Xeno Tactic 2
- update_by_query timeout
- JVM - 应用JVM核心参数推荐设置
- 对网站的代码采集实例
- 6、oracle数据库下查询操作
- 使用手机游戏的新闻推送
- 成为顶尖架构师必须要面对的面试题
- μC/OS-III---I笔记9---任务等待多个内核对象和任务内建信号量与消息队列
- PAT (Basic Level) Practice1002 写出这个数
- 免费网站源码 织梦模板下载
- VOB文件用什么软件打开,VOB文件如何转换成MP4格式
- 华为交换机Hybrid接口
- kotlin!腾讯+字节+阿里面经真题汇总,挥泪整理面经
- BUUCTF Rabbit
- 打印机设置为双面打印
- Java计算1~n的和
- 你说五毛就五毛? 生产者消费者模式(Producer Consumer Pattern)来讲解
- 【华人学者风采】李曙光 中国地质大学(北京)
热门文章
- 如何判断网页是动静态的
- idea配置docker
- WiFi P2P协议学习
- 【Optional类】JDK1.8新特性之Optional类的使用
- [Python学习] 简单爬取CSDN下载资源信息
- COCI. RIJEKA
- 第11.9节 Python正则表达式的贪婪模式和非贪婪模式
- java最大子序列和问题_一文看懂《最大子序列和问题》(内含Java,Python,JS代码)...
- C++中 cin 的详细用法
- OpenProcessToken()运用心得