40.弗洛伊德(Floyd)算法

这篇具有很好参考价值的文章主要介绍了40.弗洛伊德(Floyd)算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述

我们此前拆解过迪杰斯特拉(Dijkstra)算法,与它一样,弗洛伊德(Floyd)算法也是用于寻找给定的加权图中顶点间最短路径的算法。该算法是1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德及其团队发现的,以主要创始人 弗洛伊德 命名。
迪杰斯特拉算法通过选定的被访问顶点,求出从出发访问顶点到其他顶点的最短路径,而弗洛伊德算法中每一个顶点都是出发访问点,所以需要将每一个顶点看做被访问顶点,求出从每一个顶点到其他顶点的最短路径。

分析

设置顶点vi到顶点vk的最短路径已知为Lik,顶点vk到vj的最短路径已知为Lkj,顶点vi到vj的路径为Lij,则vi到vj的最短路径为: min((Lik+Lkj),Lij),vk的取值为无向图中所有顶点,则可获得vi到vj的最短路径。
至于vi到vk的最短路径Lik或者vk到vi的最短路径Lkj,是以同样的方式获得。

我们还是回到“郝乡长”的政绩工程——得胜乡的七村修路问题
40.弗洛伊德(Floyd)算法,数据结构与算法,算法

首先是对于各个顶点之间举例的初始化
40.弗洛伊德(Floyd)算法,数据结构与算法,算法
对于前驱关系也是我们在算法开始之前需要明晰的
40.弗洛伊德(Floyd)算法,数据结构与算法,算法
在第一轮循环中,以A(下标:0)作为中间顶点,距离表和前驱关系会更新为:

40.弗洛伊德(Floyd)算法,数据结构与算法,算法
以A为中间节点的可能性全部遍历,就会得到更新的距离表和前驱关系。

(无向图)将A作为中间节点情况有:

分析距离表的替换:

• C-A-G 距离 7+2 = 9; --------> CG (N) ------>CG(9)
• C-A-B 距离 7+5 = 12; --------> CB(N) ------>CB(12)
• G-A-B 距离 2+5 = 7; --------> GB(3) 因为7>3所以不做替换!

分析前驱关系表的替换:

• C通过A到G,故前驱关系表中,C行G列的前驱节点替换为A;
• G通过A到C,故前驱关系表中,G行C列的前驱节点替换为A;
• C通过A到B,故前驱关系表中,C行B列的前驱节点替换为A;
• B通过A到C,故前驱关系表中,B行C列的前驱节点替换为A;

如何将A作为中间节点的情况都考虑到?

中间顶点数组{A,B,C,D,E,F,G} 取A(k[0])—> …
出发顶点数组{A,B,C,D,E,F,G} 取A (i[0]) —>取B(i[1])
终点数组{A,B,C,D,E,F,G} 遍历 (j=1,2,3,…) —>(j=1,2,3,…)
时间复杂度: O(n3),较高

代码实现

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.length, matrix, vertex);

        graph.floyd();

        graph.show();

    }
}

//图
class Graph{
    private char[] vertex;//存放顶点的数组
    private int [][] dis;//保存,从各个顶点出发到其它顶点的距离,最后的结果,也是保留在该数组
    private int [][] pre;//保存到达目标顶点的前驱顶点

    /**
     * @param length 大小
     * @param matrix 邻接矩阵
     * @param vertex 顶点数组
     */
    public Graph(int length,int [][] matrix,char[]vertex) {
        this.vertex = vertex;
        this.dis = matrix;
        this.pre = new int[length][length];
        //对pre进行初始化,注意存放的是前驱顶点的下标
        for (int i = 0; i < length; i++) {
            Arrays.fill(pre[i],i);
        }
    }

    //显示pre数组和dis数组
    public void show(){
        char[] vetex = {'A','B','C','D','E','F','G'};
        for (int k = 0; k < dis.length; k++) {
            //先将pre数组输出的一行
            for (int i = 0; i < dis.length; i++) {
                System.out.print(vetex[pre[k][i]] + " ");
            }
            System.out.println();
            //输出dis数组的一行数据
            for (int i = 0; i < dis.length; i++) {
                System.out.print("("+vertex[k]+"到"+vertex[i]+"的最短路径"+dis[k][i]+") ");
            }
            System.out.println();
            System.out.println();
            
        }
        
    }

    //弗洛伊德算法
    public void floyd(){
        int len = 0 ;//变量保存
        //对中间顶点的遍历, k 就是中间顶点的下标
        for (int k = 0; k < dis.length; k++) {
            //从i顶点开始出发 [ A,B,C,D,E,F,G ]
            for (int i = 0; i < dis.length; i++) {
                //到达j顶点  [ A,B,C,D,E,F,G ]
                for (int j = 0; j < dis.length; j++) {
                    len = dis[i][k]+dis[k][j];//求出i顶点出发,经过k中间顶点,到达j顶点距离
                    if (len<dis[i][j]){//如果len < 两点的直连距离
                        dis[i][j] = len;//更新距离
                        pre[i][j] =pre[k][j];//更新前驱节点
                    }
                }
            }
        }
    }
}


关注我,共同进步,每周至少一更。——Wayne文章来源地址https://www.toymoban.com/news/detail-735014.html

到了这里,关于40.弗洛伊德(Floyd)算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 弗洛伊德(Floyd's)算法—解决最短路径经典算法

    弗洛伊德(Floyd's)算法—解决最短路径经典算法

    弗洛伊德算法(Floyd\\\'s algorithm)是一种用于解决图中最短路径问题的经典算法。由美国计算机科学家罗伯特·弗洛伊德于1962年提出,该算法通过动态规划的思想,在图中寻找任意两个节点之间的最短路径,具有广泛的应用。本文将详细介绍弗洛伊德算法的原理、实现细节以及应用

    2024年02月04日
    浏览(7)
  • 弗洛伊德(Floyd)算法求个顶点之间最短路径问题(详解+图解)

    弗洛伊德(Floyd)算法求个顶点之间最短路径问题(详解+图解)

    具体来说,弗洛伊德算法通过求解所有点对之间的最短路径来实现。在算法开始时,我们假设图中的所有节点之间都是不联通的,即它们之间的距离为无穷大。然后,我们对图进行“松弛”操作,即尝试更新每个节点之间的距离估计值,以寻找更短的路径。具体来说,对于图

    2024年02月08日
    浏览(8)
  • 【数据结构】最短路径算法实现(Dijkstra(迪克斯特拉),FloydWarshall(弗洛伊德) )

    【数据结构】最短路径算法实现(Dijkstra(迪克斯特拉),FloydWarshall(弗洛伊德) )

    最短路径问题 :从在带权有向图G中的某一顶点出发,找出一条通往另一顶点的最短路径,最短也就是沿路径各边的权值总和达到最小。 单源最短路径问题:给定一个图G = ( V , E ) G=(V,E)G=(V,E),求源结点s ∈ V s∈Vs∈V到图 中每个结点v ∈ V v∈Vv∈V的最短路径 针对一个带权

    2024年02月04日
    浏览(13)
  • 数据结构第13周 :( 迪杰斯特拉最短路径 + 弗洛伊德求最短路径 + 欧拉回路 + Invitation Cards)

    【问题描述】 在带权有向图G中,给定一个源点v,求从v到G中的其余各顶点的最短路径问题,叫做单源点的最短路径问题。 在常用的单源点最短路径算法中,迪杰斯特拉算法是最为常用的一种,是一种按照路径长度递增的次序产生最短路径的算法。 在本题中,读入一个有向图

    2024年02月13日
    浏览(13)
  • 最短路径——弗洛伊德算法

    最短路径——弗洛伊德算法

    对于这类最短路径问题,DIF算法也可以解决,只需要 定义一个二维数组 ,以 数组的横坐标作为有向网顶点的下标 , 循环n次 依次求解各个源点到其余顶点的最短路径, 时间复杂度为O(n^3) 。 由于弗洛伊德算法求解该问题的的时间复杂度同为O(n^3),而且 思路简单及代码实现

    2024年01月23日
    浏览(8)
  • 弗洛伊德循环查找算法-原理

    弗洛伊德循环查找算法-原理

    本文灵感来自哔哩哔哩视频  视频链接: 弗洛伊德循环查找算法 算法代码(java) 弗洛伊德循环查找算法中第二次相遇的地方就是循环的起始点,这个性质的证明是基于数学的原理。这是因为在第一次相遇时,慢指针 `slow` 和快指针 `fast` 已经处于同一个循环内。设链表起点到环

    2024年01月19日
    浏览(10)
  • 弗洛伊德算法(求最短路径)

    弗洛伊德算法(求最短路径)

    在一个加权图中,如果想找到各个顶点之间的最短路径,可以考虑使用弗洛伊德算法。 弗洛伊德算法既适用于无向加权图,也适用于有向加权图。使用弗洛伊德算法查找最短路径时,只允许环路的权值为负数,其它路径的权值必须为非负数,否则算法执行过程会出错。 弗洛

    2024年02月06日
    浏览(10)
  • 今天学习了弗洛伊德算法(floyed)

    我自己写的模板 嘿嘿 Dijkstra算法SPFA算法但是我知道还有这些,但是今天是周末哎,我有点不想学了,我今天学的是比较差劲的一个算法(但是它好像比较好记啊),改天再学其他比较好一点的算法加强自己 输入 输出 后言:提醒自己加权值是分题目来不同权值,不是像示例

    2024年02月11日
    浏览(6)
  • 力扣-202. 快乐数解析-弗洛伊德循环查找算法

    力扣-202. 快乐数解析-弗洛伊德循环查找算法

    题目链接   使用代码测试一下每一代数字  可以发现 归纳一下这些简单数字就可以发现,对于任意一个非快乐数,最终会进入重复循环, ···不难发现,4即之后的结果就是新一轮循环。 那么我的第一个做法是检测4出现的次数 如果4出现次数超过两次, 那么就不是快乐数 感

    2024年01月20日
    浏览(9)
  • 【力扣热题100】287. 寻找重复数(弗洛伊德的乌龟和兔子方法)

    【力扣热题100】287. 寻找重复数(弗洛伊德的乌龟和兔子方法)

    刷一道力扣热题100吧 难度中等 https://leetcode.cn/problems/find-the-duplicate-number/?envType=study-plan-v2envId=top-100-liked 一年半前做过这题,但是时间复杂度不够。现在重新学一下 主要是用到了弗洛伊德的乌龟和兔子方法 算法预览: 初始化 :从两个指针开始,“乌龟\\\"和\\\"兔子”,都指向第

    2024年02月05日
    浏览(7)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包