首页 > 编程语言 >多源最短路径算法 -- 弗洛伊德(Floyd)算法

多源最短路径算法 -- 弗洛伊德(Floyd)算法

时间:2024-06-13 11:31:25浏览次数:24  
标签:dist -- 路径 int 算法 Floyd 顶点

1. 简介

        Floyd算法,全名为Floyd-Warshall算法,亦称弗洛伊德算法或佛洛依德算法是一种用于寻找给定加权图中所有顶点对之间的最短路径的算法。这种算法以1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德的名字命名。

2. 核心思想

        通过考虑图中所有可能的中转点,逐步更新两点间的最短路径长度和路径信息,直至找到最终的最短路径。有的人也称之为插点法。

3. 图解

3.1 初始化

初始化:设置图的邻接矩阵dict,其中dict[i][j]表示顶点i到顶点j的直接路径权重;如果两顶点不直接相连,则设为无穷大INF。

3.2  更新最短路径

更新最短路径:把每个节点当作是中转节点,更新矩阵中的距离。

通过中间顶点 k 从顶点 i 到顶点 j 的距离 小于 直接从顶点 i 到顶点 j 的距离,更新 dist[i][j] = dist[i][k] + dist[k][j]

把0作为中转节点,此时表中黄色部分是不需要改的(都是从0出发或是直接到0的距离),

当更新 dict[1][2]也就是1 -> 2 时,需判断 1 -> 0 和 0 -> 2 的和是否比直达的1 -> 2更小。

更新完 0作为中转节点时 数组为:

更新完 1作为中转节点时 数组为:

 

 更新完 2作为中转节点时 数组为:

 更新完 3作为中转节点时 数组为:

3.3 结果

        最终结果的数组中就是点到点的最短路径。

4. 代码实现

        定义了一个4x4的图,其中INF表示两个顶点之间没有直接相连的边。然后调用floyd方法计算所有顶点对之间的最短路径,并输出结果。

public class Floyd {
    private static final int INF = Integer.MAX_VALUE; 

    public static void floyd(int[][] graph) {
        int n = graph.length; // 获取图的顶点数
        int[][] dist = new int[n][n]; 

        // 初始化矩阵
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                dist[i][j] = graph[i][j]; 
            }
        }

        // 使用Floyd算法计算所有顶点之间的最短路径
        for (int k = 0; k < n; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if (dist[i][k] != INF 
                            && dist[k][j] != INF
                            && dist[i][k] + dist[k][j] < dist[i][j]) { 
                        // 更新i到j的最短路径
                        dist[i][j] = dist[i][k] + dist[k][j];
                    }
                }
            }
        }

        // 输出所有顶点之间的最短路径
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print(dist[i][j] + " ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        int[][] graph = {
                {0,   5  , 3  , 10 },
                {INF, 0  , 3  , INF},
                {5  , INF, 0  , 1  },
                {INF, INF, 4  , 0  }
        };
        floyd(graph); 
    }
}

5. floyd算法和Dijkstra算法的区别

        Floyd算法和Dijkstra算法都是计算图中顶点之间最短路径的著名算法,但它们的应用场景、原理和性能存在显著差异。具体分析如下:

  • 应用场景

    • Dijkstra算法:适用于单源最短路径问题,即从单个源点到其他所有点的最短路径。它不能处理具有负权边的图。
    • Floyd算法:用于求解任意顶点对(多源最短路径问题)的最短路径,可以处理负权边,但不能处理包含负权回路的图。
  • 算法原理

    • Dijkstra算法:基于贪心策略,每次从未确定的顶点中选择一个距离源点最近的顶点,然后更新其邻接顶点的距离。该算法需要使用优先队列来选择下一个顶点,并且初始时除源点外的所有顶点的距离都设置为无穷大。
    • Floyd算法:通过动态规划的方式,利用三层嵌套循环来计算所有顶点对之间的最短路径。算法的基本操作是比较(u,k) + (k,v)与(u,v)的长度,并据此更新(u,v)的长度。
  • 时间复杂度

    • Dijkstra算法:使用优先队列优化后的时间复杂度是O((V+E) log V),其中V是顶点数,E是边数。如果使用邻接矩阵实现且没有优化,复杂度会是O(V^2)。
    • Floyd算法:时间复杂度为O(V^3),因为算法需要三层循环遍历所有顶点对和可能的中间顶点。
  • 额外功能

    • Dijkstra算法:可以输出从源点到各顶点的最短路径。
    • Floyd算法:可以输出任意两个顶点间的最短路径及其长度。

        总之,Dijkstra算法适合解决单源最短路径问题,尤其是在没有负权边的情况下,而Floyd算法适合解决所有顶点对之间的最短路径问题,尽管它可以处理负权边的情况,却不能容忍负权回路的存在。

        

6. 总结 

        总的来说,Floyd算法是一种计算图中所有顶点对之间最短路径的动态规划算法,它能够处理包含负权边的图,但不允许存在负权回路。适用于小型到中等规模稠密图的算法,尤其是在需要全局最短路径信息时。对于大型稀疏图或者单源最短路径问题,其他算法如Dijkstra算法可能更加合适。

标签:dist,--,路径,int,算法,Floyd,顶点
From: https://blog.csdn.net/qq_67342067/article/details/139534687

相关文章

  • CSP_J_真题之 2023 第一轮笔试(一)
    公众号:编程驿站......
  • Wireshark网络分析从入门到实践【1.2】
            如果在这个期间你没有从事过其他的网络活动(例如在线看视频、下载等),那么现在最上方的也就是流量最大的对话就是在你的浏览器和www.wireshark.org之间建立的。        从图1-10中可以看出来,104.25.219.21与192.168.1.102之间对话产生的流量最多为21......
  • Java工程师技术提升汇总【1.1】
    4.6.VIM键盘图第5章网络配置和系统管理操作5.1查看网络IP和网关1)查看虚拟网络编辑器2)修改ip地址5.2配置网络ip地址5.2.1ifconfig配置网络接口ifconfig:networkinterfacesconfiguring网络接口配置1)基本语法:ifconfig(功能描述:显示所有网络接口......
  • 随心笔记,第六更
    目录一、 三步构建XML转成javabean1.XML转XSD2.XSD转JavaBean 3.jaxb工具类4.测试......
  • Java环境搭建——JDK安装和环境搭建
    1、开发Java程序需要:JDK+源代码编辑器;        JDK:Java开发工具包;        源代码编辑器:有windows记事本,eclipse,IntellijIDEA(推荐)等2、Java——半编译半解析型编译语言      Java语言能够跨平台是因为Java程序需要在JVM上运行......
  • Java——语言基础
    标识符标识符命名规则Java中标识符用来标记包、类、接口、对象、方法、变量等名称    1、字母、下划线(_)、美元符号($)开头,不能以数字开头;    2、Java对字母大小写敏感,大写和小写是完全不一样的;    3、不能和关键字相同;    4、不能含有空......
  • 力扣刷题记录: 1339. 分裂二叉树的最大乘积
        本题是第174场周赛的Q3,LC竞赛分为1675.方法一.递归(超时)    单纯使用递归对每一个节点进行遍历,代码如下:classSolution{longlongans=-1;public:intmaxProduct(TreeNode*root){longlongtotal_sum=sum(root);......
  • Map集合体系大介绍
    1.Map集合体系Map集合体系概述(Map系列集合的特点都是由键决定的,值只是一个附属品,值是不做要求的):在Map接口下,主要有两个实现类HashMap(LinkedHashMap是在HashMap基础上的另一个实现类)和TreeMap实现类。HashMap(由键决定特点):无序、不重复、无索引用的最多(利用hashCode和......
  • 力扣刷题记录: 1424. 对角线遍历Ⅱ
        本题是第182场周赛的Q3,LC竞赛分为1780。方法一.利用反对角线性质    在同一条反对角线上的元素的i+j值是相同的,同时,根据遍历的方式可知,i值越大的元素在同一条反对角线之中越先被遍历,i+j值越小的反对角线越早被遍历。考虑采用有序的map对i+j......
  • FlowUs本地部署:数据自主权与定制化服务的完美融合|FlowUs息流企业级解决方案本地私有化
    在当今数字化时代,企业对数据的控制和安全性要求越来越高,同时,用户对软件的使用习惯也趋向多样化。针对这些需求,FlowUs作为一款多功能的协作平台,提供了灵活的解决方案。FlowUs本地部署对于有本地化需求的客户,FlowUs支持企业私有化部署服务。这意味着企业可以根据自己的需求,在本......