正在载入交互式动画窗口请稍等

Floyd(弗洛伊德)算法 可视化交互式动画版

图码-数据结构可视化动画版
>

Floyd -Warshall 算法 以其创始人 Robert Floyd 和 Stephen Warshall 命名,是计算机科学和图论中的基本算法。 它用于查找加权图中所有节点对之间的最短路径。 该算法非常高效,可以处理具有 正边 权重和 负边权重的 图,使其成为解决各种网络和连接问题的多功能工具。

弗洛伊德·沃歇尔(Floyd-Warshall)算法:

Floyd Warshall 算法 全对最短路径算法,与单源最短路径算法 Dijkstra Bellman Ford 不同。 该算法适用于 有向 无向加权 图。 但是,它不适用于具有负循环的图(其中循环中的边的总和为负)。 它遵循 动态规划 方法来检查经过每个可能节点的每条可能路径,以计算每对节点之间的最短距离。

Floyd Warshall 算法背后的想法:

假设我们有一个图 G[][] ,其中 V 个 顶点从 1 N 现在我们必须评估 shortestPathMatrix[][] ,其中 s hortestPathMatrix[i][j]表示顶点 i j 之间的最短路径

显然, i j 之间的最短路径 将有 k 个中间节点。 Floyd Warshall 算法背后的思想是将1 N 中的每个顶点逐一视为 中间节点。

下图展示了上述floyd warshall算法中的最优子结构性质:

算法:

  • 第一步,初始化与输入图矩阵相同的解矩阵。 
  • 然后通过将所有顶点视为中间顶点来更新解矩阵。 
  • 这个想法是一一挑选所有顶点并更新所有最短路径,其中包括作为最短路径中的中间顶点的挑选顶点。 
  • 当我们选择顶点编号 k 作为中间顶点时,我们已经将顶点 {0, 1, 2, .. k-1} 视为中间顶点。 
  • 对于每对 (i, j) 源顶点和目标顶点,有两种可能的情况。 
    • k 不是从 i j 的最短路径中的中间顶点。 我们保持dist[i][j] 的值 不变。 
    • k是从 i j 的 最短路径中的中间顶点 我们将dist[i][j] 的值更新 dist[i][k] + dist[k][j], 如果 dist[i][j] > dist[i][k] + dist[k] [j]

伪代码:

对于 k = 0 到 n – 1
对于 i = 0 到 n – 1
对于 j = 0 到 n – 1
距离[i, j] = min(距离[i, j], 距离[i, k] + 距离[k , j])

其中 i = 源节点,j = 目标节点,k = 中间节点

插图:

假设我们有一个如图所示的图:

dryRun1drawio

步骤 1 使用输入图初始化 Distance[][] 矩阵,使得 Distance[i][j]= 从 i j 的边的权重,如果从 i 没有边,则 Distance[i][j] = Infinity j。

步骤1绘制

步骤 2 :将节点 A 视为中间节点,并使用以下公式计算每个 {i,j} 节点对的 Distance[][]:

= 距离[i][j] = 最小值 (距离[i][j], (从 i 到 A 的距离) + (从 A 到 j 的距离 )) = 距离[i][j] = 最小值 (距离[i] [j], 距离[i][ A ] + 距离[ A ][j])

步骤2绘图

步骤 3 :将节点 B 视为中间节点,并使用以下公式计算每个 {i,j} 节点对的 Distance[][]:

= 距离[i][j] = 最小值 (距离[i][j], (从 i 到 B 的距离) + (从 B 到 j 的距离 )) = 距离[i][j] = 最小值 (距离[i] [j], 距离[i][ B ] + 距离[ B ][j])

步骤3画图

步骤 4 :将节点 C 视为中间节点,并使用以下公式计算每个 {i,j} 节点对的 Distance[][]:

= 距离[i][j] = 最小值 (距离[i][j], (从 i 到 C 的距离) + (从 C 到 j 的距离 )) = 距离[i][j] = 最小值 (距离[i] [j], 距离[i][ C ] + 距离[ C ][j])

步骤4绘图

步骤 5 :将节点 D 视为中间节点,并使用以下公式计算每个 {i,j} 节点对的 Distance[][]:

= 距离[i][j] = 最小值 (距离[i][j], (从 i 到 D 的距离) + (从 D 到 j 的距离 )) = 距离[i][j] = 最小值 (距离[i] [j], 距离[i][ D ] + 距离[ D ][j])

步骤5画图

步骤 6 :将节点 E 视为中间节点,并使用以下公式计算每个 {i,j} 节点对的 Distance[][]:

= 距离[i][j] = 最小值 (距离[i][j], (从 i 到 E 的距离) + (从 E 到 j 的距离 )) = 距离[i][j] = 最小值 (距离[i] [j], 距离[i][ E ] + 距离[ E ][j])

步骤6绘图

步骤7 :由于所有节点都被视为中间节点,我们现在可以返回更新后的Distance[][]矩阵作为我们的答案矩阵。

步骤7绘图

下面是上述方法的实现:

C++

// C++ Program for Floyd Warshall Algorithm
#include <bits/stdc++.h>
using namespace std;
 
// Number of vertices in the graph
#define V 4
 
/* Define Infinite as a large enough
value.This value will be used for
vertices not connected to each other */
#define INF 99999
 
// A function to print the solution matrix
void printSolution(int dist[][V]);
 
// Solves the all-pairs shortest path
// problem using Floyd Warshall algorithm
void floydWarshall(int dist[][V])
{
 
    int i, j, k;
 
    /* Add all vertices one by one to
    the set of intermediate vertices.
    ---> Before start of an iteration,
    we have shortest distances between all
    pairs of vertices such that the
    shortest distances consider only the
    vertices in set {0, 1, 2, .. k-1} as
    intermediate vertices.
    ----> After the end of an iteration,
    vertex no. k is added to the set of
    intermediate vertices and the set becomes {0, 1, 2, ..
    k} */
    for (k = 0; k < V; k++) {
        // Pick all vertices as source one by one
        for (i = 0; i < V; i++) {
            // Pick all vertices as destination for the
            // above picked source
            for (j = 0; j < V; j++) {
                // If vertex k is on the shortest path from
                // i to j, then update the value of
                // dist[i][j]
                if (dist[i][j] > (dist[i][k] + dist[k][j])
                    && (dist[k][j] != INF
                        && dist[i][k] != INF))
                    dist[i][j] = dist[i][k] + dist[k][j];
            }
        }
    }
 
    // Print the shortest distance matrix
    printSolution(dist);
}
 
/* A utility function to print solution */
void printSolution(int dist[][V])
{
    cout << "The following matrix shows the shortest "
            "distances"
            " between every pair of vertices \n";
    for (int i = 0; i < V; i++) {
        for (int j = 0; j < V; j++) {
            if (dist[i][j] == INF)
                cout << "INF"
                     << " ";
            else
                cout << dist[i][j] << "   ";
        }
        cout << endl;
    }
}
 
// Driver's code
int main()
{
    /* Let us create the following weighted graph
            10
    (0)------->(3)
        |     /|\
    5 |     |
        |     | 1
    \|/     |
    (1)------->(2)
            3     */
    int graph[V][V] = { { 0, 5, INF, 10 },
                        { INF, 0, 3, INF },
                        { INF, INF, 0, 1 },
                        { INF, INF, INF, 0 } };
 
    // Function call
    floydWarshall(graph);
    return 0;
}
 
// This code is contributed by Mythri J L


            

C

Java

Python3

C#

Javascript

PHP

输出

下面的矩阵显示了每对顶点之间的最短距离
0 5 8 9   
中导号 0 3 4   
中标 中标 0 1   
INF INF 0   

复杂性分析

  • 时间复杂度: O(V 3 ),其中 V 是图中的顶点数,我们运行三个嵌套循环,每个循环的大小为 V
  • 辅助空间: O(V 2 ),创建一个二维矩阵,以存储每对节点的最短距离。

注意 :上述程序仅打印最短距离。 我们还可以通过将前驱信息存储在单独的二维矩阵中来修改解决方案以打印最短路径。 

为什么 Floyd-Warshall 算法更适合密集图而不是稀疏图?

密集图 :边数明显多于顶点数的图。
稀疏图 :边数非常少的图。

无论图中有多少条边, Floyd Warshall 算法 都会运行 O(V 3 ) 次,因此它最适合 密集图 在稀疏图的情况下, 约翰逊算法 更适合。

与弗洛伊德·沃歇尔(Floyd-Warshall)相关的重要面试问题:

  • 如何使用 Floyd Warshall 算法检测图中的负循环?
  • Floyd-warshall 算法与 Dijkstra 算法有何不同?
  • Floyd-warshall 算法与 Bellman-Ford 算法有何不同?

Floyd-Warshall 算法的现实应用:

  • 在计算机网络中,该算法可用于查找网络中所有节点对之间的最短路径。 这称为 网络路由
  • 航班连接 在航空业中寻找机场之间的最短路径。
  • GIS 地理信息系统 )应用通常涉及分析空间数据(例如道路网络),以找到位置之间的最短路径。
  • Kleene 算法 是 Floyd Warshall 的推广,可用于查找正则语言的正则表达式。

无论你的目标是考试成功、职业发展,还是纯粹的兴趣,这个数据结构和算法可视化的网站都会是一个无价的资源。

前往这个网站,开始你的学习之旅吧!

这些是常见的:【C语言描述】《数据结构和算法》数据结构JAVA实现 数据结构与算法基础(青岛大学-王卓)数据结构与算法王道数据结构c语言实现 速成数据结构期末考前救急 数据结构视频C语言版教程 数据结构严蔚敏 数据结构郝斌 数据结构考研 JAVA数据结构算法与基础 数据结构王道 2022数据结构学习 数据结构小甲鱼 王卓 学习数据结构 数据结构浙江大学 数据结构复习 数据结构马士兵 数据结构零基础教程 数据结构和算法 数据结构入门 考研数据结构习题讲解 数据结构期末复习 计算机二级