尚硅谷课程:数据结构与算法中弗洛伊德算法的最短路径求法

目录

1 弗洛伊德算法介绍

2 弗洛伊德算法中三大数组更新思路

3 最短路径实现思路

4 核心代码实现

5 调用并输出路径结果

6 结果展示

7 总结


1 弗洛伊德算法介绍

弗洛伊德算法(Floyd's algorithm),又称为全源最短路径算法,是一种用于解决图中所有节点之间最短路径的经典算法。

该算法的基本思想是通过动态规划的方式逐步更新路径长度,从而找到所有节点之间的最短路径。具体步骤如下:

  1. 创建一个二维数组dis,其中dis[i][j]表示节点i到节点j的最短路径长度的估计值。初始时,dis[i][j]的值为节点i到节点j的直接距离(如果两个节点之间有边相连),或者为无穷大(如果两个节点之间没有边相连)。

  2. 创建一个二维数组pre,其中pre[i][j]表示节点i到节点j的最短路径上节点j的前一个节点的索引。初始时,pre[i][j]的值为j(即节点j是节点i到节点j的最短路径上的前一个节点)。

  3. 对于每对节点i和j,以及所有中间节点k,检查是否存在一条经过节点k的路径,使得经过节点k的路径长度更短。如果存在这样的路径,则更新dis[i][j]pre[i][j]的值。

    • 如果dis[i][j] > dis[i][k] + dis[k][j],则更新dis[i][j]dis[i][k] + dis[k][j],并更新pre[i][j]为节点k的索引。
  4. 重复第3步,对所有的节点i、j和k进行遍历,直到所有节点之间的最短路径长度都被计算出来。

  5. 最终,dis数组中的值即为所有节点之间的最短路径长度,pre数组中的值可以用于回溯路径,从而得到最短路径的具体节点序列。

2 弗洛伊德算法中三大数组更新思路

在弗洛伊德算法中,有三个关键的数组需要更新:dis数组、pre数组和result数组。

  1. dis数组的更新:

    在算法的初始化阶段,dis数组会被初始化为图中各个节点之间的直接距离。然后,在算法的迭代过程中,会逐步更新dis数组中的值,以得到最短路径的长度。

    更新dis数组的过程是通过遍历中间节点k的方式进行的。对于每一对节点i和j,如果经过节点k的路径长度更短,则更新dis[i][j]的值为dis[i][k] + dis[k][j]

    更新公式为:dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j])

  2. pre数组的更新:

    pre数组用于记录最短路径上每个节点的前一个节点的索引。在算法的迭代过程中,当更新dis[i][j]的值时,也需要更新pre[i][j]的值。

    更新pre数组的过程是通过将节点k作为中间节点时的情况进行判断。如果经过节点k的路径长度更短,则更新pre[i][j]的值为节点k的索引。

    更新公式为:pre[i][j] = pre[k][j]

  3. result数组的更新:

    result数组用于存储最终的最短路径结果,即图中所有顶点对之间的最短路径。

    在算法的迭代过程中,每当更新dis[i][j]的值时,也需要更新result[i][j]的值。根据路径的构建过程,可以根据pre数组的值回溯路径,并将路径的节点顺序存储到result[i][j]中。

    具体的路径构建过程在您提供的代码中已经进行了实现。

总的来说,弗洛伊德算法通过不断更新dis数组和pre数组的值,以及构建路径来寻找图中所有节点之间的最短路径。这些数组的更新是算法的核心步骤,通过动态规划的思想逐步更新路径长度和前一个节点的索引,从而得到最短路径的结果。

本篇主要讲解和实现更新路径的问题.

3 最短路径实现思路

弗洛伊德算法的时间复杂度为O(n^3),其中n是图中节点的数量。它适用于解决有向图或无向图中任意两个节点之间的最短路径问题。

  1. 首先,创建一个二维数组result,用于存储最终的结果,即图上所有顶点对之间的最短路径。

  2. 使用两个嵌套的for循环遍历二维数组dis,其中dis是存储顶点之间距离的二维数组。

  3. 在每个循环中,获取当前顶点对应的起点和终点,并创建一个空的StringBuilder对象path用于构建路径。

  4. 对于特殊情况,当起点等于终点时,直接将终点添加到path中,表示路径只包含自身。

  5. 对于一般情况,通过查找pre数组来获取前一个顶点的索引。从终点开始,依次添加前一个顶点到path中,直到前一个顶点等于起点。

  6. 由于路径是从终点到起点的顺序,因此需要将path进行反转,使其变为起点到终点的顺序。

  7. 对于i > j的情况,直接从result数组中获取路径结果,并进行反转操作。

  8. 将构建好的路径字符串转换为String类型,并存储到result数组的对应位置。

4 核心代码实现

/**
     * 根据前驱节点数组来创建一下结果数组,数组中存放能使图中所有节点对连通的距离最短的路径
     */
    private void createResult() {
        //打印最终的结果 也就是 打印出 图上所有顶点对儿的间相连的距离最短的那个路径
        result = new String[vertexList.size()][vertexList.size()];
        StringBuilder path = null;
        for (int i = 0; i < dis.length; i++) {
            for (int j = 0; j < dis.length; j++) {
                String start = vertexList.get(i);
                String end = vertexList.get(j);
                path = new StringBuilder();
                //如果是自己 也就是 i==j时 直接打印start(或end)即可
                if (i == j) {
                    path.append(end);
                } else if (i < j) {
                    int preIndex = pre[i][j];
                    path.append(end);
                    while (preIndex != i) {
                        path.append("-").append(vertexList.get(preIndex));
                        preIndex = pre[i][preIndex];
                    }
                    path.append("-").append(start);
                    path.reverse();
                } else {
                    path = new StringBuilder(result[j][i]).reverse();
                }
                result[i][j] = String.valueOf(path);
            }
        }
    }

5 调用并输出路径结果

//根据上面的createResult方法来打印输出一下路径结果
    public void showResult() {
        //先把结果给我创建好了
        createResult();
        System.out.println("\n所有顶点对之间的最短路径如下:");
        for (int i = 0; i < result.length; i++) {
            for (int j = 0; j < result.length; j++) {
                String start = vertexList.get(i);
                String end = vertexList.get(j);
                System.out.printf("    %s - %s: %-8s", start, end, result[i][j]);
            }
            System.out.println();
        }
    }

6 结果展示

7 总结

        总体而言,以上代码实现了弗洛伊德算法中创建最短路径数组的逻辑。它正确地根据dis数组和pre数组构建了最短路径,并将结果存储在result数组中。然而,为了确保代码的正确性,建议在实际使用前进行测试和验证,尤其是对于pre数组的更新和路径的起点和终点的顺序进行仔细检查。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤尘Java

感谢认可!感谢您的打赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值