最短路径算法:Floyd-Warshall算法

引言

在图论中,Floyd-Warshall算法是一种用于计算任意两点之间最短路径的动态规划算法。它适用于加权有向图和无向图,可以处理带有负权重边的图,但要求图中不能有负权重环。本文将详细介绍Floyd-Warshall算法的定义、步骤及其实现。

Floyd-Warshall算法

定义

Floyd-Warshall算法是一种用于计算图中所有顶点对之间最短路径的算法。该算法利用动态规划的思想,通过不断更新顶点对之间的最短路径,最终得到所有顶点对的最短路径矩阵。

算法步骤

  1. 初始化:创建一个距离矩阵dist,其中dist[i][j]表示顶点i到顶点j的初始距离。如果i和j之间有边,则dist[i][j]为边的权重;如果i和j之间没有边且i≠j,则dist[i][j]为正无穷大;如果i=j,则dist[i][j]为0。
  2. 更新距离矩阵:对于每一对顶点(i, j),通过中间顶点k更新其最短路径。具体来说,如果dist[i][j] > dist[i][k] + dist[k][j],则更新dist[i][j] = dist[i][k] + dist[k][j]。
  3. 重复更新:重复上述步骤,直到所有顶点对之间的最短路径都被计算出来。

示例

假设我们有一个带权有向图,顶点集合为 ({A, B, C, D}),边和权重集合为 ({(A, B, 3), (A, C, 8), (A, D, -4), (B, D, 1), (B, C, -2), (C, A, 4), (D, C, 7), (D, B, -5)})。
3 8 -4 1 -2 4 7 -5 A B C D

Floyd-Warshall算法图解

  1. 初始化距离矩阵
plaintext 复制代码
  A   B   C   D
A 0   3   8  -4
B ∞   0  -2   1
C 4  ∞   0  ∞
D ∞  -5   7   0
  1. 通过顶点A更新距离矩阵
plaintext 复制代码
  A   B   C   D
A 0   3   8  -4
B 7   0  -2   1
C 4  ∞   0  ∞
D 3  -5   7   0
  1. 通过顶点B更新距离矩阵
plaintext 复制代码
  A   B   C   D
A 0   3   1  -4
B 5   0  -2   1
C 4  7   0  ∞
D 3  -5   2   0
  1. 通过顶点C更新距离矩阵
plaintext 复制代码
  A   B   C   D
A 0   3   1  -4
B 5   0  -2   1
C 4  7   0  ∞
D 3  -5   2   0
  1. 通过顶点D更新距离矩阵
plaintext 复制代码
  A   B   C   D
A 0  -1   1  -4
B 5   0  -2   1
C 4  -1   0  -3
D 3  -5   2   0

Floyd-Warshall算法实现

下面是用Java实现Floyd-Warshall算法的代码示例:

java 复制代码
import java.util.Arrays;

public class FloydWarshallAlgorithm {
    private static final int INF = 99999; // 表示无穷大的值

    // 计算任意两点之间的最短路径
    public void floydWarshall(int[][] graph) {
        int vertices = graph.length;
        int[][] dist = new int[vertices][vertices];

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

        // 更新距离矩阵
        for (int k = 0; k < vertices; k++) {
            for (int i = 0; i < vertices; i++) {
                for (int j = 0; j < vertices; j++) {
                    if (dist[i][k] != INF && dist[k][j] != INF && dist[i][k] + dist[k][j] < dist[i][j]) {
                        dist[i][j] = dist[i][k] + dist[k][j];
                    }
                }
            }
        }

        printSolution(dist);
    }

    // 打印最短路径矩阵
    private void printSolution(int[][] dist) {
        int vertices = dist.length;
        System.out.println("顶点对之间的最短路径矩阵:");
        for (int i = 0; i < vertices; i++) {
            for (int j = 0; j < vertices; j++) {
                if (dist[i][j] == INF) {
                    System.out.print("INF ");
                } else {
                    System.out.print(dist[i][j] + "   ");
                }
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        int[][] graph = {
            {0, 3, 8, -4},
            {INF, 0, -2, 1},
            {4, INF, 0, INF},
            {INF, -5, 7, 0}
        };
        FloydWarshallAlgorithm floydWarshall = new FloydWarshallAlgorithm();
        floydWarshall.floydWarshall(graph);
    }
}

代码注释

  1. 常量定义

    java 复制代码
    private static final int INF = 99999; // 表示无穷大的值

    INF 表示无穷大,用于表示顶点之间没有直接连接。

  2. Floyd-Warshall算法

    java 复制代码
    public void floydWarshall(int[][] graph) {
        int vertices = graph.length;
        int[][] dist = new int[vertices][vertices];
    
        // 初始化距离矩阵
        for (int i = 0; i < vertices; i++) {
            for (int j = 0; j < vertices; j++) {
                dist[i][j] = graph[i][j];
            }
        }
    
        // 更新距离矩阵
        for (int k = 0; k < vertices; k++) {
            for (int i = 0; i < vertices; i++) {
                for (int j = 0; j < vertices; j++) {
                    if (dist[i][k] != INF && dist[k][j] != INF && dist[i][k] + dist[k][j] < dist[i][j]) {
                        dist[i][j] = dist[i][k] + dist[k][j];
                    }
                }
            }
        }
    
        printSolution(dist);
    }

    floydWarshall 方法实现了Floyd-Warshall算法,计算任意两点之间的最短路径。

  3. 打印最短路径矩阵

    java 复制代码
    private void printSolution(int[][] dist) {
        int vertices = dist.length;
        System.out.println("顶点对之间的最短路径矩阵:");
        for (int i = 0; i < vertices; i++) {
            for (int j = 0; j < vertices; j++) {
                if (dist[i][j] == INF) {
                    System.out.print("INF ");
                } else {
                    System.out.print(dist[i][j] + "   ");
                }
            }
            System.out.println();
        }
    }

    printSolution 方法用于打印最短路径矩阵。

结论

通过上述讲解和实例代码,我们详细展示了Floyd-Warshall算法的定义、步骤及其实现。Floyd-Warshall算法是一种重要的最短路径算法,适用于计算任意两点之间的最短路径。希望这篇博客对您有所帮助!


如果您觉得这篇文章对您有帮助,请关注我的CSDN博客,点赞并收藏这篇文章,您的支持是我持续创作的动力!


关键内容总结

  • Floyd-Warshall算法的定义
  • Floyd-Warshall算法的步骤
  • Floyd-Warshall算法的实现及其

代码注释


推荐阅读:深入探索设计模式专栏 ,详细讲解各种设计模式的应用和优化。点击查看:深入探索设计模式


特别推荐:设计模式实战专栏 ,深入解析设计模式的实际应用,提升您的编程技巧。点击查看:设计模式实战

如有任何疑问或建议,欢迎在评论区留言讨论。谢谢阅读!

相关推荐
小蜗牛慢慢爬行5 分钟前
有关异步场景的 10 大 Spring Boot 面试问题
java·开发语言·网络·spring boot·后端·spring·面试
荒古前12 分钟前
龟兔赛跑 PTA
c语言·算法
Colinnian15 分钟前
Codeforces Round 994 (Div. 2)-D题
算法·动态规划
Algorithm157615 分钟前
云原生相关的 Go 语言工程师技术路线(含博客网址导航)
开发语言·云原生·golang
用户00993831430121 分钟前
代码随想录算法训练营第十三天 | 二叉树part01
数据结构·算法
shinelord明25 分钟前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
新手小袁_J30 分钟前
JDK11下载安装和配置超详细过程
java·spring cloud·jdk·maven·mybatis·jdk11
呆呆小雅30 分钟前
C#关键字volatile
java·redis·c#
დ旧言~31 分钟前
专题八:背包问题
算法·leetcode·动态规划·推荐算法