【数据结构】图—弗洛伊德(Floyd)算法
前言
上文介绍了迪杰斯特拉(Dijkstra)算法,计算网图的某个源点到其余各个顶点的最短路径问题(边权值为非负值),本文介绍另一个求最短路径的算法——弗洛伊德算法,它是计算所有顶点到所有顶点的最短路径,其时间复杂度为O(n3)O(n^3)O(n3),其算法相比Dijkstra算法更加简洁易懂。
算法思路
在迪杰斯特拉算法中,定义了两个一维数组int D[MAXVEX]
和 int P[MAXVEX]
,D表示源点到其他顶点的最短路径和,P表示对应顶点的最小路径的前驱矩阵。
因为弗洛伊德算法中,以所有顶点为源点,因此应该定义为二维数组int D[MAXVEX][MAXVEX]
和 int P[MAXVEX][MAXVEX]
,核心思路和迪杰斯特拉算法类似,从源点v
到终点w
,判断经过中转点k
的路径是否比原来的路径更短。
例如下图中,A顶点
到B顶点
在邻接矩阵中是10,如果经过C顶点
中转,则路径和为4+3=74+3 = 74+3=7,显然要比直接路径要短。
D[v][w]=min{D[v][w],D[v][k]+D[k][w]}D[v][w] = min\{ D[v][w],\quad D[v][k] + D[k][w] \} D[v][w]=min{D[v][w],D[v][k]+D[k][w]}
以某一顶点为中转点,遍历所有顶点为源点和终点,如果经过中转点更短,则将D中的相应位置更新。
以下面这个网图为例,观察一下具体是怎么计算的。
(1)其邻接矩阵如下,也是D
数组的初始化矩阵。
P
矩阵初始化如下:
首先以A顶点为中转点,没有经过A点的最短路径;再以B点为中转点,A-D
时,因为$10+1 = 11 < \infty $,所以对应的D[0][3]
和D[3][0]
改为11,P[0][3]
和P[3][0]
分别改为P[0][1]
和P[3][1]
。C-D
时,因为3+1=4<93+1 = 4 < 93+1=4<9,所以对应的D[2][3]
和D[3][2]
改为4,P[2][3]
和P[3][2]
改为P[2][1]
和P[3][1]
。
(2)以C顶点为中转点,A-B时,因为4+3=7<104+3=7 < 104+3=7<10,所以D[0][1] = D[1][0] = 7
,P[0][1] = P[1][0] = 2
。
A-D时,因为D[0][2]+D[2][3]=8<11D[0][2] + D[2][3] = 8 < 11D[0][2]+D[2][3]=8<11,所以D[0][3] = D[3][0] = 8
,P[0][3] = P[0][2] = 2
,P[3][0] = P[3][2] = 1
。
A-E时,因为D[0][2]+D[2][4]=6<7D[0][2] + D[2][4] = 6 < 7D[0][2]+D[2][4]=6<7,所以D[0][4] = D[4][0] = 6
,P[0][4] = P[4][0] = 2
。
B-E时,因为 D[1][2]+P[2][4]=5>∞D[1][2] + P[2][4] = 5 > \inftyD[1][2]+P[2][4]=5>∞,所以D[1][4] = D[4][1] = 5
,P[1][4] = P[4][1] = 2
。
(3)然后依次以D、E顶点为中转点,遍历所有源点到顶点的路径情况,没有经过D、E中转点的最短路径,D、P矩阵不变。
算法程序
(1)程序第6-13行,是对D和P矩阵初始化;
(2)程序第14-29行,包含了三层for
嵌套,分别是中转点k,源点v,终点w,需要注意的是,中转点k的循环必须放在外面,如果放在内循环中,则表示在最开始就计算两个顶点之间的最短距离,(比如计算A-D的最短路径,此时遍历所有中转点,得到的结果是A-B-D
:11,显然是不正确的),中转点k在外循环,不断的收缩各顶点之间的距离,从而求得最短路径。
typedef int Pathmatirx_floyd[MAXVEX][MAXVEX];
typedef int ShortPathTable_floyd[MAXVEX][MAXVEX];
void ShorttestPath_Floyd(MGraph G, Pathmatirx_floyd *P, ShortPathTable_floyd *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]; //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的顶点}}}}
}
测试程序
#include "CreateGraph.h"
#include "floyd.h"int main()
{MGraph G;CreateMgraph(&G);Pathmatirx_floyd fP;ShortPathTable_floyd fD;ShorttestPath_Floyd(G, &fP, &fD);ShowShortPath_Floyd(G, fP, fD);return 0;
}void ShowShortPath_Floyd(MGraph G, Pathmatirx_floyd P, ShortPathTable_floyd D)
{int v, w, k;for (v = 0; v < G.numVertexes; v++){for(w = v+1; w < G.numVertexes; w++){printf("%c - %c weight: %d", G.vexs[v], G.vexs[w], D[v][w]);k = P[v][w];printf(" path: %c", G.vexs[v]);while (k != w){printf(" -> %c", G.vexs[k]);k = P[k][w];}printf(" -> %c\n", G.vexs[w]);}printf("\n");}}
总结
弗洛伊德(Floyd)算法优点是程序简洁,且计算了所有顶点之间的最短路径问题,缺点是
因为是三层循环,时间复杂度为O(n3)O(n^3)O(n3),对于不需要计算所有顶点之间的最短路径时,其效率较低。
迪杰克斯特拉(Dijkstra)和弗洛伊德(Floyd)这两种求最短路径的算法,一个是求某一源点到其余顶点的最短路径,一个是求所有顶点之间的最短路径,他们也都适用于(权值非负值)有向图,与无向图的区别仅仅在于邻接矩阵是否对称。
【数据结构】图—弗洛伊德(Floyd)算法相关推荐
- 数据结构——图——弗洛伊德(Floyd)算法
数据结构--图--弗洛伊德(Floyd)算法 为了能讲明白弗洛伊德(Flbyd)算法的精妙所在,我们先来看最简单的案例.图7-7-12的左图是一个最简单的3个顶点连通网图. 我们先定义两个二维数组D[ ...
- 数据结构与算法(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 ...
最新文章
- 在ElasticSearch之下(图解搜索的故事)
- MATLAB新手教程
- javafx透明边框_JavaFX技巧6:使用透明颜色
- 洛谷P1014 [NOIP1999 普及组] Cantor 表
- TensorFlow全球下载量破1亿,Jeff Dean激动不已
- Telnet和FTP
- activerecord java_GitHub - redraiment/jactiverecord: 实现自己的ORM还是有价值的
- 学习【新版的】韦东山嵌入式_day01
- KeyCloak实现单点登录说明
- 计算机excel求体重指数,excel标准差-制程能力指数(CPK)的定义及计算公式
- html代码广告代码大全,强制弹窗广告代码大全.doc
- python编写脚本暴力破解6位纯数字密码
- 【网络】路由器集成锐捷认证
- 融金所:云办公提升P2P金融“生命”
- ubuntu20.04下搜狗输入法不能输中文问题解决
- 【Poco学习笔记】Poco库介绍
- 【CodeForces 767C】Garland (树形DP)
- Framework 修改默认输入法
- 转:网页游戏都有哪些安全问题
- 计算机用户名如何保存,电脑的用户名和密码怎么查看