文章目录

  • 一、弗洛伊德算法概述
  • 二、弗洛伊德算法的思想与步骤
    • 2.1 基本思想
    • 2.2 步骤图解说明
  • 三、弗洛伊德算法的代码实现

一、弗洛伊德算法概述

在上一篇博客 图解迪杰斯特拉算法(最短路径问题) 中介绍了迪杰斯特拉算法,该算法用于求解单源最短路径问题。所谓单源最短路径路径就是从某一个顶点出发,求解其到各个顶点的最短路径。

那么如果想要求解每一对顶点之间的最短路径,该怎么做呢?

其实可以对迪杰斯特拉进行简单的改造,就可以实现上述目的。既然迪杰斯特拉是用于计算单个源点到各个顶点之间的最短路径,那么只需要对每个顶点都执行一次迪杰斯特拉算法,便可以得到每一对顶点之间的最短路径。迪杰斯特拉的时间复杂度是 O(n²),如果对每个顶点都执行一次,那么时间复杂度将变为 O(n³)。

不过,对迪杰斯特拉算法改造来计算每对顶点之间的最短路径在代码实现上是比较复杂的,这里我们学习一种新的算法,叫做弗洛伊德(Floyd)算法

弗洛伊德算法在求解每一对顶点之间的最短路径问题的代码实现上相对于迪杰斯特拉算法简单很多,它的时间复杂度也是 O(n³)。

二、弗洛伊德算法的思想与步骤

2.1 基本思想

通常从源点到终点,并不是直接到达的,而是需要经过许多中转站来一步步到达。例如下图,<V4,V5>、<V5,V2> 之间的距离分别为 4 和 5。可以看到,V4 和 V2 之间不能直接通达,如果要计算 V4 和 V2 之间的距离,我们就要借助 V5 来作为中转站,因此 V4 到 V2 的距离为 4+5=9。

如果要计算 V4 和 V3 之间的距离呢?这个时候只借助 V5 就无法完成任务了,还需要额外借助 V2。

因此,计算所有节点之间的最短距离这个大问题可以分为借助 k 个中转站的情况下计算各节点之间的最短路径,其中 0 ≤ k ≤ |V|。

弗洛伊德算法的基本思想如下

假设求从顶点 vi 到 vj 的最短路径。如果从 vi 到 vj 有边,则从 vi 到 vj 存在一条长度为 dis[i][j] (dis 为邻接矩阵)的路径,但是该路径不一定是最短路径,还需要再进行 n 次试探。首先考虑路径 <vi,v0,vj> 是否存在(即 <vi,v0> 、<v0,vj>),如果存在,则比较 <vi,vj> 和 <vi,v0,vj> 的路径长度,然后取较小者为 vi 到 vj 的最短路径,且 vi 到 vj 的中间顶点的序号不大于 0。假如在路径上再增加一个一个顶点 v1,也就是说,如果 <vi,…,v1> 和 <v1,…,vj> 分别是当前找到的中间顶点的序号不大于 0 (即中间顶点可能是 v0 或没有)的最短路径,那么<vi,…,v1,…,vj> 就有可能是从 vi 到 vj 的中间顶点的序号不大于 1 的最短路径。将它和已经得到的从 vi 到 vj 中间顶点序号不大于 0 的最短路径相比较,从中选出中间顶点的序号不大于 1 的最短路径之后,再增加一个顶点 v2,继续进行试探。以此类推,直到增加了所有的顶点作为中间节点。

弗洛伊德算法的核心思想总结下来就是:不断增加中转顶点,然后更新每对顶点之间的最短距离

2.2 步骤图解说明

如下图所示,演示使用弗洛伊德算法求解每一对顶点之间的最短路径。

  1. 在没有中转点的情况下,各个顶点之间的最短路径距离,用一个二维数组 dis 表示,如下图所示。

  2. 假设 v1 作为中转点,则各个顶点之间的最短路径距离理论上将会被更新。然而由于 v2 经中转点 v1 到 v3 的距离大于 v2 直接到 v3 的距离(即 dis[v2][v1] + dis[v1][v3] > dis[v2][v3]),因此本次最短路径距离并未真正发生变化。

  3. 再假设 v1,v2 作为中转点。此时 v5 可以经 v2 访问到 v1 和 v3,在没有中转的情况下,v5 到 v1 和 v3 的最短距离都是无穷大,因此各个顶点之间的最短路径距离将会被更新。

  4. 再假设 v1,v2,v3 作为中转点。此时 v1 经 v3 访问 v2 的距离小于直接访问 v2 的距离(即 dis[v1][v3] + dis[v3][v2] < dis[v1][v2]),因此 v1 到 v2 的最短距离将会被更新;同时由于 v1 需经 v2 中转访问 v5,因此 v1 到 v5 的最短距离也要同步更新。

  5. 再假设 v1,v2,v3,v4 作为中转点。由于 v4 是一个孤立的中转点因此,因此各个顶点之间的最短路径并未发生真正变化。

  6. 再假设 v1,v2,v3,v4,v5 作为中转点。由于 v2 经 v5 中转可达 v4 且距离小于 dis[v2][v4],因此 v2 到 v4 的最短路径将会更新 ,且 v1,v3 到 v4 的最短路径也会随之更新。

  7. 至此,所有的点都作为了中转点,算法执行完毕。此时 dis 数组中存放的就是各个顶点之间的最短路径距离。

三、弗洛伊德算法的代码实现

public class FloydAlgorithm {private static final int N = 65535;    // 表示距离无穷大public static void main(String[] args) {String[] vertexes = { "v1", "v2", "v3", "v4", "v5"};    // 顶点int[][] dis = {  // 各个顶点之间的初始最短路径/*v1*//*v2*//*v3*//*v4*//*v5*//*v1*/{0,    6,    3,    N,    N},/*v2*/{6,    0,    2,    N,    5},/*v3*/{3,    2,    0,    N,    N},/*v4*/{N,    N,    N,    0,    4},/*v5*/{N,    5,    N,    4,    0},};floyd(dis); // 调用弗洛伊德算法/* 输出每一对顶点之间的最短距离 */for (int i=0; i<dis.length; i++){for (int j=0; j<dis[i].length; j++){System.out.printf("<%s,%s> = %d \t",vertexes[i],vertexes[j],dis[i][j]);}System.out.println();}}/*** 弗洛伊德算法求解每一对顶点之间的最短路径距离* @param dis   初始最短路径距离*/public static void floyd(int[][] dis){for (int k=0; k<dis.length; k++){   // 遍历中转顶点for (int i=0; i<dis.length; i++){   // 从下标为 i 的顶点出发for (int j=0; j<dis.length; j++){   // 终点下标为 j/* 如果经新的中转点后的最短路径距离小于 dis[i][j],就更新 dis[i][j] */if (dis[i][k] + dis[k][j] < dis[i][j]){dis[i][j] = dis[i][k] + dis[k][j];}}}}}}

运行结果如下:

图解弗洛伊德算法(每一对顶点之间的最短路径问题)相关推荐

  1. 每一对顶点之间的最短路径

    // func7-2.cpp 算法7.16,algo7-7.cpp和algo7-9.cpp用到 void ShortestPath_FLOYD(MGraph G,PathMatrix P,Distan ...

  2. 弗洛伊德算法(求每一对顶点间的最短路径)

    每一对顶点间的最短路径 求解每一对顶点间的最短路径有两种方法:其一是分别以图中的每个顶点为源点共调用n次迪杰斯特拉算法:其二是采用下面介绍的弗洛伊德算法.这两种算法的时间复杂度均为O(n^3),但后者 ...

  3. 【笔记】每一对顶点间的最短路径

    每一对顶点间的最短路径 弗洛伊德算法 弗洛伊德算法的实现 1.每一对顶点间的最短路径   如果要计算每一对顶点之间的最短路径,需每次以一个顶点为出发点,将迪杰斯特拉算法重复执行n次,就可以得到每一对顶 ...

  4. C++ 实现带权有向图的每对顶点之间的最短路径Floyd算法(完整代码)

    基本思想是: 假设求从顶点vi到vj的最短路径. 如果从vi到vj有弧,则从vi到vj存在一条长度为arcs[i][j]的路径,该路径不一定是最短路径,尚需进行n次试探. 首先考虑路径(vi, v0, ...

  5. 使用Floyd-Warshall算法求出两点之间的最短路径

    求出下面任意两个点之间的最短路径: 如何才能求出两点之间的最短路径呢?大家都知道学几何的时候,有一条定理就是:两点之间线段最短.但是在实际情况中,我往往两点之间没有之间的通路而是一些曲折的线路. 上面 ...

  6. 最短路径之迪杰斯特拉(Dijkstra 算法)弗洛伊德算法(C语言完整代码实现)

    写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站.博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事 ...

  7. 【数据结构】所有顶点对的最短路径 Floyd算法

    所有顶点对的最短路径问题是指:对于给定的有向图G=(V,E),求任意一对顶点之间的最短路径. 可以求解得到的  的递推公式: #include <stdio.h> #include < ...

  8. 弗洛伊德算法Floyed(求各顶点间最短路径):可打印最短路径

    #include <iostream> #include <string> #include <iomanip> using namespace std; #def ...

  9. 最短路径:Dijkstra算法(求单源最短路径)Floyd算法(求各顶点之间最短路径)

    最短路径: 在一个带权图中,顶点V0到图中任意一个顶点Vi的一条路径所经过边上的权值之和,定义为该路径的带权路径长度,把带权路径最短的那条路径称为最短路径. DiskStra算法: 求单源最短路径,即 ...

最新文章

  1. 告别渣画质,视频会议带宽降90%,英伟达公开Maxine服务背后重要技术
  2. 团队作业8----第二次项目冲刺(Beta阶段) 第六天
  3. 【WebAPI No.5】Core WebAPI中的自定义格式化
  4. html 物流状态,css+html如何实现物流进度样式(代码示例)
  5. php教学小结,php小结
  6. windows7下iis网站的.net框架版本设置
  7. 用node-webkit开发多平台的桌面客户端
  8. 六万字最全总结Java数据库编程MyBatis(+收藏)
  9. VTD-传感器使用小结
  10. Mac系统如何安装Eclipse并搭建Android开发环境
  11. 【计量经济学】工具变量估计与两阶段最小二乘法
  12. 女生学UI合适吗?橙色优学告诉你女生UI设计优势
  13. Win7常见问题和技巧整
  14. 网站漏洞修复公司 对网站上传文件漏洞的修复与安全加固
  15. Invalid bound statement (not found): com.xxx.mapper.xxxMapper.selectxxx
  16. list(map(tokenizer.tokenize, text))
  17. mac os x excel 单元格换行
  18. mac excel 换行 快捷键
  19. opencv4.5.2嵌入式移植
  20. MyBatis(一)—— 2h学完这篇就可以入门mybatis啦

热门文章

  1. 记录一次node.jsV14升级到V16遇到问题并解决
  2. 循环队列front==rear
  3. linux下删除一个环境变量,Linux 添加环境变量和删除环境变量
  4. 深入理解Amazon Alexa Skill(三)
  5. [教程] ESP32+TFT+分光棱镜实现透明小电视
  6. MPC5744P-UART(LIN)模块
  7. An Introduction to Pairing-Based Cryptography学习笔记
  8. 小程序wx.request通过post方式提交数据给服务器-小程序支付开发教程
  9. oCPC基础知识了解
  10. 万万没想到,“红孩儿”竟然做了程序员,还是CTO!