最短路径算法: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算法的实现及其

代码注释


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


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

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

相关推荐
不爱写代码的玉子1 分钟前
HALCON透视矩阵
人工智能·深度学习·线性代数·算法·计算机视觉·矩阵·c#
Java 技术轻分享7 分钟前
《树数据结构解析:核心概念、类型特性、应用场景及选择策略》
数据结构·算法·二叉树··都差速
我很好我还能学21 分钟前
【面试篇 9】c++生成可执行文件的四个步骤、悬挂指针、define和const区别、c++定义和声明、将引用作为返回值的好处、类的四个缺省函数
开发语言·c++
芜湖xin32 分钟前
【题解-洛谷】P1706 全排列问题
算法·dfs
程序员JerrySUN33 分钟前
[特殊字符] 深入理解 Linux 内核进程管理:架构、核心函数与调度机制
java·linux·架构
2302_8097983237 分钟前
【JavaWeb】Docker项目部署
java·运维·后端·青少年编程·docker·容器
蓝婷儿42 分钟前
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
开发语言·python·学习
渣渣盟1 小时前
基于Scala实现Flink的三种基本时间窗口操作
开发语言·flink·scala
网安INF1 小时前
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
java·web安全·网络安全·flink·漏洞
一叶知秋哈1 小时前
Java应用Flink CDC监听MySQL数据变动内容输出到控制台
java·mysql·flink