[ 数据结构 ] 弗洛伊德算法(Floyd)--------最短路径问题

news/2024/11/27 21:52:32/

0 Floyd算法介绍

  1. 和 Dijkstra 算法一样,弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的算法。该算法名称以创始人之一、1978 年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名
  2. 弗洛伊德算法(Floyd)计算图中各个顶点之间的最短路径
  3. 迪杰斯特拉算法用于计算图中某一个顶点到其他顶点的最短路径。
  4. 弗洛伊德算法 VS 迪杰斯特拉算法:迪杰斯特拉算法通过选定的被访问顶点,求出从出发访问顶点到其他顶点的最短路径;弗洛伊德算法中每一个顶点都是出发访问点,所以需要将每一个顶点看做被访问顶点,求出从每一个顶点到其他顶点的最短路径。
  5. 回顾:迪杰斯特拉算法

1 Floyd算法应用

image-20230109204119269.png

最短路径问题:

  1. 胜利乡有 7 个村庄(A, B, C, D, E, F, G)
  2. 各个村庄的距离用边线表示(权) ,比如 A – B 距离 5 公里
  3. 问:如何计算出各村庄到 其它各村庄的最短距离?

思路分析:

  1. 核心思想:穷举
  2. 三层for循环分别使3个指针指向三个顶点,最外层表示中间顶点k
  3. k=0则表示A顶点作为中间顶点,那么就可以更新BC和CG间的最短路径
  4. k从0->6,则可以得到所有顶点间的最短路径
  5. 当然想法简单,但是实现起来需要借助辅助变量,这里用到初始值为邻接矩阵的距离表dis和初始值为出发点的前驱关系表pre

image-20230109235216136.png

image-20230109235233631.png

个人理解:

  1. 为什么如此初始化前驱关系表?

    因为默认开始只有两种路线:直连/不直连,两种情况下默认前驱节点都是出发点,即出发点到任何顶点的前驱节点都是自己,至于后续的改动,不管最短路线改为非直连的两段还是三段,也只是针对不直连的路(即65535),而直连的两个顶点相关数据无需改动,前驱自然就是终点的前驱节点,即出发点

  2. 两顶点之间非直连,最短路径为3段的,最短路径是怎么更新的,如CD的最短路径为CEFD?

    观察:虽然F作为中间点,但是测试时中间点第一个就用F,CD的距离和前驱都未能更新,仅更新了DE之间和DG之间数据,而当F之后的E作为中间点,CD之间数据才能更新,即CD的前驱为F,为什么会如此?

    注意:这是因为F作为中间点时,CEFD中存在65535,即CF间距此时还是65535所以CD无法更新,而E作为中间点时之前更新了ED=EF+FD,所以CD=CE+ED,CD相关数据才得以更新

    结论:当MN两点之间最短路径需要经过n个顶点,那么只有当这n个中间点的相关数据全部更完,MN间的数据才能更新,也可以说,想更新MN的数据,必须保证路径上没有65535

//弗洛伊德算法:最短路径问题
public class FloydAlgorithm {public static void main(String[] args) {//测试看看图是否创建成功char[] vertex = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };//创建邻接矩阵int[][] matrix = new int[vertex.length][vertex.length];final int N = 65535;matrix[0] = new int[] { 0, 5, 7, N, N, N, 2 };matrix[1] = new int[] { 5, 0, N, 9, N, N, 3 };matrix[2] = new int[] { 7, N, 0, N, 8, N, N };matrix[3] = new int[] { N, 9, N, 0, N, 4, N };matrix[4] = new int[] { N, N, 8, N, 0, 5, 4 };matrix[5] = new int[] { N, N, N, 4, 5, 0, 6 };matrix[6] = new int[] { 2, 3, N, N, 4, 6, 0 };Graph graph = new Graph(vertex, matrix);graph.floyd();graph.show();}
}class Graph {private char[] vertex;private int[][] dis;private int[][] pre;public Graph(char[] vertex, int[][] matrix) {this.vertex = vertex;//初始化最短路径数组为邻接矩阵,直连就是最短路径,非直连则需要找this.dis = matrix;pre = new int[vertex.length][vertex.length];for (int i = 0; i < pre.length; i++) {//这里为什么如此初始化前驱节点?//答:因为默认开始只有两种路线:直连/不直连,两种情况下默认前驱节点都是出发点,即出发点到任何顶点的前驱节点都是自己//  至于后续的改动,不管最短路线改为非直连的两段还是三段,也只是针对不直连的路(即65535),//  而直连的两个顶点相关数据无需改动,前驱自然就是终点的前驱节点,即出发点Arrays.fill(pre[i], i);}}public void show() {for (int i = 0; i < vertex.length; i++) {for (int p : pre[i]) {System.out.print(vertex[p]+" ");}System.out.println();for (int j = 0; j < vertex.length; j++) {System.out.print("["+vertex[i]+"->"+vertex[j]+"="+dis[i][j]+"] ");}System.out.println("\n");}}public void floyd() {int len = 0;//问题:两顶点之间非直连,最短路径为3段的,最短路径是怎么更新的,如CD的最短路径为CEFD?//答://  观察:虽然F作为中间点,但是测试时中间点第一个就用F,CD的距离和前驱都未能更新,仅更新了DE之间和DG之间数据,//      而当F之后的E作为中间点,CD之间数据才能更新,即CD的前驱为F,为什么会如此?//  注意:这是因为F作为中间点时,CEFD中存在65535,即CF间距此时还是65535所以CD无法更新,而E作为中间点时之前更新了ED=EF+FD//      所以CD=CE+ED,CD相关数据才得以更新//  结论:当MN两点之间最短路径需要经过n个顶点,那么只有当这n个中间点的相关数据全部更完,MN间的数据才能更新//      也可以说,想更新MN的数据,必须保证路径上没有65535int[] range = {5,4,3,2,1,0,6};for (int k : range) {//BC CGSystem.out.println(vertex[k] + "作为中间节点");for (int i = 0; i < vertex.length; i++) {for (int j = 0; j < vertex.length; j++) {len = dis[i][k] + dis[k][j];if (len < dis[i][j]) {System.out.println("修改了:[" + vertex[i] + "-" + vertex[j] + "]");dis[i][j] = len;//直连的前驱(出发点)改为非直连后半段(最后一段)的前驱(出发点)//举例:AE>AG+GE,所以A(pre[AE])=G(pre[GE])pre[i][j] = pre[k][j];}}}}}
}

http://www.ppmy.cn/news/10958.html

相关文章

C#编程遇到的问题合集(2023.1.9)

文章目录1.Partial类2.MessageBox的用法3.Static类和Static变量4.SubString函数用法5.读取指定文件内容的一般格式6.二进制字符串转换为十进制数字7.给窗口添加任务栏图标8.给窗口设置最大化和最小化按钮1.Partial类 Partial类的意思是定义一个类的一部分。也就是说&#xff0…

异步path怎么约?

异步path怎么约? 在design里往往会有一些特殊需求,例如约束两个异步clock之间的path,而异步path对于工具来说往往是不做任何约束的,那么我们应该怎么去对异步clock之间的path做约束呢? 异步clock 异步clock可以通过两个办法来约束: 1、set_clock_group 2、set_false_p…

汤姆斯的天堂梦(C++,Dijkstra)

题目描述 汤姆斯生活在一个等级为 000 的星球上。那里的环境极其恶劣&#xff0c;每天 121212 小时的工作和成堆的垃圾让人忍无可忍。他向往着等级为 NNN 的星球上天堂般的生活。 有一些航班将人从低等级的星球送上高一级的星球&#xff0c;有时需要向驾驶员支付一定金额的费…

EEG论文阅读和分析:《Differential entropy feature for EEG-based emotion classification》

论文阅读《Differential entropy feature for EEG-based emotion classification》 论文的核心是提出差分熵作为特征&#xff0c;并且对差分差分熵和比例差分熵等特征进行对比研究。 算法流程步骤&#xff1a; 采样过程&#xff1a; A.预处理 根据受试者的压力反应&#xf…

指针详解——高级指针的解析及应用

目录 &#x1f411;指针的初步了解 &#x1f402;指针的深入认识 &#x1f99b;1.指针数组 &#x1f400;指针数组的介绍 &#x1f400;指针数组的用法介绍 &#x1f42b;2.数组指针 &#x1f98c;数组指针的介绍以及使用 &#x1f9ae;3.函数指针 &#x1f408;函数指针的介绍…

【数据结构与算法】——第六章:图

文章目录1、图的定义1.1 图的其他定义1.2 图的顶点与边之间的关系1.3 连通图相关术语2、图的存储结构2.1 邻接矩阵2.2 邻接表3、图的遍历3.1 深度优先遍历3.2 广度优先遍历4、最小生成树4.1 普利姆算法(Prim)4.2 克鲁斯卡尔(kruskal)5、最短路径5.1 迪杰斯特拉(Dijkstra)算法5.…

【图的存储】

更好的阅读体验\color{red}{更好的阅读体验}更好的阅读体验 文章目录1. 邻接矩阵2. 边集数组3. 邻接表4. 链式邻接表5. 链式前向星总结1. 邻接矩阵 思想&#xff1a; 利用二维数组 g[N][N] 存储所有的点到点的权值。其中 N 为点的数量&#xff0c;g[i][j] 表示点 i 到点 j 的权…

外业调查工具助手,照片采集、精准定位、导航、地图查看

你是不是在外业调查时要背着一堆图纸 是不是一不小心图纸污损或丢失&#xff0c;工作又得重做 是不是经常会出现图纸标注的空间不足 是不是外业采集中要携带一大堆繁琐的仪器 是不是每次收集的数据、照片等在整理的过程中发现工作量巨大 是不是经常会出现采集回来的内容跟…