首页 > 编程语言 >弗洛伊德(Floyd's)算法—解决最短路径经典算法

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

时间:2023-10-11 23:32:07浏览次数:38  
标签:弗洛伊德 dist 路径 算法 Floyd INF 节点

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

弗洛伊德(Floyd

一、原理

  1. 动态规划思想:弗洛伊德算法利用了动态规划的思想,将原问题分解为子问题并进行逐步求解。它通过不断更新节点之间的最短路径长度来逐步求解任意两个节点之间的最短路径。
  2. 三重嵌套循环:弗洛伊德算法通过三重嵌套的循环进行迭代更新。具体地说,对于每个中间节点k,算法会遍历所有的节点对(i, j),并比较直接从i到j的路径和经过节点k的路径哪个更短,然后更新节点i到j的最短路径长度。
  3. 动态规划转移方程:在每次迭代更新中,通过以下动态规划转移方程来更新节点i到j的最短路径长度:D[i][j] = min(D[i][j], D[i][k] + D[k][j])其中,D[i][j]表示从节点i到节点j的最短路径长度,D[i][k]表示从节点i到节点k的最短路径长度,D[k][j]表示从节点k到节点j的最短路径长度。
  4. 初始化:在算法开始之前,需要将图中节点之间的距离填入二维数组中。如果两个节点之间有直接的边相连,则距离为边的权值,否则距离设为无穷大。
  5. 迭代更新过程:算法使用三重嵌套的循环依次遍历所有节点对(i, j)和中间节点k,根据动态规划转移方程更新节点i到j的最短路径长度。
  6. 输出结果:经过多轮迭代更新后,最终得到的二维数组中存储了任意两个节点之间的最短路径长度。
  7. 总体而言,弗洛伊德算法通过动态规划的思想,在图中寻找任意两个节点之间的最短路径。它通过不断迭代和更新节点之间的最短路径长度,最终得到了图中所有节点之间的最短路径长度。这种算法思想简单而有效,可以解决各种实际问题。

二、实现

  1. 初始化:首先,我们需要创建一个二维数组dist来存储任意两个节点之间的最短路径长度。数组的大小为n × n,其中n是图中节点的个数。初始化时,将数组所有元素的值设为无穷大,表示暂时没有找到节点之间的最短路径。
  2. 填充初始距离:接下来,我们需要遍历图中的边,将直接相连的节点之间的距离填入dist数组。如果两个节点之间有直接的边相连,则将边的权值填入对应位置的数组元素。
  3. 迭代更新:接着,我们进行多轮的迭代更新操作,每轮都遍历所有的节点对(i, j)和中间节点k。对于每个节点对(i, j),我们检查从节点i到节点j经过节点k的路径是否比直接从节点i到节点j的路径更短。如果是,则更新节点i到节点j的最短路径为经过节点k的路径长度。具体地,我们使用以下动态规划转移方程来进行更新:dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])这个过程将会进行n轮,每次迭代都会尝试更新所有节点对(i, j)的最短路径长度。
  4. 输出结果:经过n轮的迭代更新后,dist数组中存储了任意两个节点之间的最短路径长度。这个二维数组可以作为算法的输出结果,我们可以通过查询该数组来获取任意两个节点之间的最短路径长度。

在实际实现时,可以使用双重循环来遍历图中的节点对(i, j),并在内部嵌套一个循环来遍历中间节点k。通过比较当前的最短路径和经过中间节点k的路径的长度,更新最短路径长度。在算法结束后,我们可以返回存储最短路径长度的dist数组。

值得注意的是,由于弗洛伊德算法是基于动态规划的思想,每个节点对之间的最短路径长度会通过多次迭代逐步更新。因此,在实现过程中需要使用合适的数据结构来存储和更新路径长度,以确保正确性和效率。

总而言之,弗洛伊德算法的实现包括初始化距离数组、填充初始距离、迭代更新和输出结果这几个关键步骤。通过这些步骤,我们可以找到图中任意两个节点之间的最短路径长度。

以下是弗洛伊德算法的代码实现:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#define INF INT_MAX
#define MAXN 100

int dist[MAXN][MAXN];
int n;

void floyd() {
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (dist[i][k] != INF && dist[k][j] != INF &&
                        dist[i][j] > dist[i][k] + dist[k][j]) {
                    dist[i][j] = dist[i][k] + dist[k][j];
                }
            }
        }
    }
}

int main() {
    printf("Enter the number of nodes: ");
    scanf("%d", &n);

    // Initialize the distance matrix
    printf("Enter the weight matrix:\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", &dist[i][j]);
            if (dist[i][j] == -1) {
                dist[i][j] = INF;
            }
        }
    }

    // Run Floyd algorithm
    floyd();

    // Print the result
    printf("All pairs shortest path:\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (dist[i][j] == INF) {
                printf("INF ");
            } else {
                printf("%d   ", dist[i][j]);
            }
        }
        printf("\n");
    }

    return 0;
}

首先定义了一个二维数组dist来存储任意两个节点之间的距离。在函数floyd中,使用三重循环遍历所有节点对(i, j)和中间节点k,并根据动态规划转移方程更新i到j的最短路径长度。在主函数中,首先输入图的节点数n和相邻节点之间的距离,然后运行floyd函数来寻找所有节点对之间的最短路径。最后,将最短路径距离打印出来作为结果。

需要注意的是,在输入距离矩阵时,使用-1表示两个节点之间没有边连接。因此,需要将其转换为INF以方便后续计算。如果节点之间有直接的连接,则输入其权值即可。

三、应用

弗洛伊德算法广泛应用于网络路由算法、城市交通规划、航空航线的优化等领域。它可以在有向图或无向图中寻找最短路径,因此被用于解决许多实际问题。

例如,在网络路由中,弗洛伊德算法可以被用来确定数据包在互联网中传输的最佳路径。通过计算任意两个节点之间的最短路径,可以找到一个延迟最小的传输路径,从而提高网络的传输效率。

在城市交通规划中,弗洛伊德算法可以帮助确定最短的行驶路线,减少交通拥堵和时间成本。利用该算法,可以计算出任意两个地点之间的最短路径,并为驾驶员提供最佳行驶建议。

此外,弗洛伊德算法还可以用于解决航空航线的优化问题。航空公司可以利用该算法计算不同城市之间的最短路径,以便合理安排航班并优化飞行时间和燃料消耗。

以下是举个例子使用弗洛伊德算法解决最短路径问题:

假设有如下的图结构,其中节点A、B、C、D代表图中的四个节点,边上的数字表示节点之间的距离:

    1
A ----> B
^       |
3       | 1
|       v
D <---- C
    2

我们可以将这个图表示为一个4x4的距离矩阵,其中INF表示节点之间没有直接的连接:

   A   B   C   D
A  0   1  INF  3
B INF  0    1 INF
C INF INF   0   2
D  3  INF INF  0

现在我们使用弗洛伊德算法来计算任意两个节点之间的最短路径。我们先用INF初始化距离矩阵dist,并填入已知的直接连接的节点之间的距离:

   A   B   C   D
A  0   1  INF  3
B  1   0    1 INF
C INF  1    0   2
D  3 INF    2   0

接下来,我们进行多轮的迭代更新,首先考虑经过节点A的情况:

当k=A时,对于节点对(i, j),我们检查从节点i到节点j经过节点A的路径是否比直接从节点i到节点j的路径更短。根据转移方程,我们有:

dist[A][B] = min(dist[A][B], dist[A][A] + dist[A][B]) = min(1, 0 + 1) = 1
dist[A][C] = min(dist[A][C], dist[A][A] + dist[A][C]) = min(INF, 0 + INF) = INF
dist[A][D] = min(dist[A][D], dist[A][A] + dist[A][D]) = min(3, 0 + 3) = 3

更新后的距离矩阵如下:

   A   B   C   D
A  0   1  INF  3
B  1   0    1 INF
C INF  1    0   2
D  3 INF    2   0

然后,我们考虑经过节点B的情况:

当k=B时,根据转移方程,我们有:

dist[B][A] = min(dist[B][A], dist[B][B] + dist[B][A]) = min(1, 0 + 1) = 1
dist[B][C] = min(dist[B][C], dist[B][B] + dist[B][C]) = min(1, 0 + 1) = 1
dist[B][D] = min(dist[B][D], dist[B][B] + dist[B][D]) = min(INF, 0 + INF) = INF

更新后的距离矩阵如下:

   A   B   C   D
A  0   1    1   3
B  1   0    1 INF
C INF  1    0   2
D  3 INF    2   0

然后,我们考虑经过节点C和D的情况,进行迭代更新。最终得到的距离矩阵如下:

   A   B    C   D
A  0   1    1   3
B  1   0    1   3
C  3   1    0   2
D  3   3    2   0

最后,我们通过查询距离矩阵可以得到任意两个节点之间的最短路径长度。例如,节点A到节点C的最短路径长度为1,节点B到节点D的最短路径长度为3。

这就是使用弗洛伊德算法解决矩阵问题的具体过程。通过多轮迭代更新,我们可以找到图中任意两个节点之间的最短路径长度。

弗洛伊德(Floyd

四、复杂度分析

弗洛伊德算法的时间复杂度为O(n3),其中n为图中节点的个数。这是因为算法需要进行三重嵌套的循环来更新每对节点之间的最短路径。

在实际应用中,如果图的规模非常大,可能需要考虑优化算法的效率。一种常见的优化方法是使用空间换时间的策略,通过记录中间节点的信息,避免重复计算。另外,如果图是稀疏的,可以使用邻接表等数据结构来表示图,以减少存储空间和计算开销。

五、总结

弗洛伊德算法是一种经典的用于求解最短路径的算法,通过动态规划的思想,在图中寻找任意两个节点之间的最短路径。它的原理简单、实现方便,并且具有广泛的应用价值。无论是网络路由、城市交通规划还是航空航线优化,弗洛伊德算法都可以发挥重要作用。通过深入了解和应用该算法,我们能够更好地解决实际问题,提升系统的效率和性能。

标签:弗洛伊德,dist,路径,算法,Floyd,INF,节点
From: https://blog.51cto.com/wamtar/7816996

相关文章

  • 代码随想录算法训练营第一天(python) | 704. 二分查找、27. 移除元素。
    Leetcode704二分查找题目链接:704二分查找关键点思路:1、是否要进入到while部分的代码是left<=right还是left<right,看[left,right]是否是合法区间.例如[1,1]是合法区间,取<=;[1,1)非合法区间,取<。2、缩小区间时,考虑边界是否已经比较过。左闭右闭区......
  • 【RF分类】基于粒子群优化随机森林PSO-RF实现数据分类算法研究附matlab代码可直接运行
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 【leach协议】基于粒子群算法改进能量均衡高效WSN的LEACH协议附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 《算法学习专栏》—— DP问题之背包模型
    2023年10月11日更新于2023年10月11日一、前言本栏,为背包模型,题目主要来源日常,目前主要来源于Acwing的提高课。希望以后做到背包的题目,也能加进来,不断完善。使用的分析方法均为闫式DP分析法。字臭。。。希望能用手写板慢慢写的好看。二、背包模型2.1目前的模型01背包模型......
  • 花朵识别系统Python+TensorFlow+Django+网页界面+算法模型
    一、介绍花朵识别系统,使用Python作为主要编程语言进行开发,使用TensorFlow搭建卷积神经网络算法模型,并基于多种花朵数据集进行模型训练,最后得到一个精度较高的h5模型文件。并基于Django框架搭建网页端可视化操作界面。实现用户上传一张花朵图片,识别其名称。二、效果图片展示......
  • JAVA图搜索算法之DFS-BFS
    图算法DFS与BFSBFS和DFS代表对图进行遍历,即搜索的算法,搜索算法中常用的只要有两种算法:深度优先遍历(Depth-First-Search:DFS)和广度优先遍历(Breadth-First-Search:BFS)。一个图结构可以用来表示大量现实生活中的问题,比如,道路网络,计算机网络,社交网络,用户身份解析图①DFS......
  • 开学过半 (cf补题和算法训练)
    Problem-A-Codeforces题意:给你一个n/2个元素的b数组,然后让你构造出一个n个元素的排列数组其中这些p数组里的数有以下要求注意这个p数组要求你搞字典序最小,也就是最好小的元素在前面如果b =[4,3,6],那么可以从中得到的词法最小排列是p =[1,4,2,3,5,6],因为:b1=max(p1,p......
  • Pollard-Rho 算法
    Miller-Rabin素性检测部分内容摘自题解P4718/论Miller-Rabin算法的确定性化-It'sLUNATICtime!)根据费马小定理,若\(p\)为素数,那么对于\(1\leqa<p\),都有\(a^{p-1}\equiv1\pmodp\)。因此,若存在\(1\leqa<p\)使得\(a^{p-1}\not\equiv1\pmodp\),那么......
  • 关于算法竞赛中标识符命名的几点建议
    头图 引言标识符命名,一个OIer每天都在做,却基本从未在意过的操作。好的命名,既可以提高自己的调试效率,也可以提高代码可读性。方便自己,也方便别人。如果你觉得自己的代码不是很美观,又觉得码风已经定型,不如继续往下看,说不定可以让你的码风更进一步。欢迎@你身边有需要的......
  • C++ - STL算法
    5STL-常用算法 概述:算法主要是由头文件<algorithm><functional><numeric>组成。 <algorithm>是所有STL头文件中最大的一个,范围涉及到比较、交换、查找、遍历操作、复制、修改等等<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数<funct......