最短路径-Floyd算法的matlab实现.md「建议收藏」

最短路径-Floyd算法的matlab实现.md「建议收藏」最短路径-Floyd算法的matlab实现​ 弗洛伊德算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或有向图或负权(但不可存在负权回路)的最短路径问题。​ 在Floyd算法中一般有两个矩阵,一个距离矩阵D,一个路由矩阵R,其中距离矩阵用于存储任意两点之间的最短距离,而路由矩阵则记录任意两点之间的最短路径信息。其思想是:如果可以从一个点进行中转,就进行比较从这个点中转和不中转的距…

大家好,又见面了,我是你们的朋友全栈君。

最短路径-Floyd算法的matlab实现

​ 弗洛伊德算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或有向图或负权(但不可存在负权回路)的最短路径问题。

​ 在Floyd算法中一般有两个矩阵,一个距离矩阵D,一个路由矩阵R,其中距离矩阵用于存储任意两点之间的最短距离,而路由矩阵则记录任意两点之间的最短路径信息。

其思想是:如果可以从一个点进行中转,就进行比较从这个点中转和不中转的距离,存储距离小的情况,并更新距离矩阵和路由矩阵

从算法思想中我们可以大概推断我们要遍历n个中转点,在每个中转点进行操作的时候,需要对任意两点之间 的距离进行遍历。那么算法就应该有三重循环,第一重循环是遍历中转点,第二重和第三重循环是遍历任意两个点之间的距离。假设中转节点为K,那么节点i与j之间的最小距离怎么更新呢?
D ( i , K ) + D ( K , j ) &lt; D ( i , j ) D(i,K)+D(K,j) &lt; D(i,j) D(i,K)+D(K,j)<D(i,j)

其中D(i,K)+D(K,j)表示i到j从K中转的距离,D(i,j)表示从i到j的最短距离,如果前者比后者小,那么就D(i,j)进行更新: D ( i , j ) = D ( i , K ) + D ( K , j ) D(i,j) = D(i,K)+D(K,j) D(i,j)=D(i,K)+D(K,j),这样就更新了距离矩阵。怎么记录这条最短路径呢,这个时候就需要更新我们的路由矩阵: R ( i , j ) = R ( i , K ) R(i,j) = R(i,K) R(i,j)=R(i,K)

路由矩阵很好理解,比如最开始是R(4,3) = 3,表示V4到V3一步就可以到达V3,如果现在可以从V2中转到达,那么R(4,3) = R(4,2) =2,表示V4->V3要先经过V2才能到达。

​ 下面我将用一个简单的例子来说明,下面是一个简单的例子:
在这里插入图片描述

这个时候我们可以写出距离矩阵D和路由矩阵R如下:


最短路径-Floyd算法的matlab实现.md「建议收藏」最短路径-Floyd算法的matlab实现.md「建议收藏」

上面是初始的距离矩阵和路由矩阵,现在我们假设:**图中的每个点之间可以经由V1中转**。这个时候我们再来判断任意两点之间的最短距离。

可以由V1中转,那么V1到到各个点的距离还是不变。V2没有到达V1的路径,所以也就不存在从V1中转的情况,所以V2到各个点的距离还是不变。

V3可以经由V1中转,那么这个时候判断一下中转前和中转后的距离大小,将最小距离留存下来如:

V3->V1 = 7 不变

V3->V2 = inf,经由V1中转之后V3->V1->V2 = 9, 于是V3到V2的最短距离变化为9,更新路由矩阵R(3,2) = R(3,1) = 1

V3->V4 = 1,经由V1中转之后V3->V1->V4 = 11, 于是V3到V4的最短距离就还是1

同理:

V4->V2 = inf, 经由V1中转之后V4->V1->V2 = 7, 于是V4到V2的最短距离变化为7,更新路由矩阵R(4,2) = R(4,1) = 1

V4->V3 = 12,经由V1中转之后V4->V1->V3 = 11, 于是V4到V2的最短距离变化为11,更新路由矩阵R(4,3) = R(4,1) = 1

那么距离矩阵和路由矩阵变化为:


最短路径-Floyd算法的matlab实现.md「建议收藏」
最短路径-Floyd算法的matlab实现.md「建议收藏」

现在假设在从V1中转的基础上,图中的每个点之间还可以经由V2中转,于是:

V1->V2 = 2

V1->V3 = 6,经由V2中转之后V1->V2->V3 = 5, 于是V1到V3的最短距离变化为5,更新路由矩阵R(1,3) = R(1,2) = 2

V1->V4 = 4

V2->V1 = inf

V2->V3 = 3

V2->V4 = inf

V3->V1 = 7

V3->V2 = 9

V3->V4 = 1

V4->V1 = 5

V4->V2 = 7

V4->V3 = 11,经由V2中转之后V4->V2->V3 = 10, 于是V4到V3的最短距离变化为10,更新路由矩阵R(4,3) = R(4,2) = 1。

于是现在的距离矩阵和路由矩阵可以变为:


最短路径-Floyd算法的matlab实现.md「建议收藏」
最短路径-Floyd算法的matlab实现.md「建议收藏」

现在假设在从V1中转的基础上,图中的每个点之间还可以经由V3中转,于是:

V1->V2 = 2

V1->V3 = 5

V1->V4 = 4

V2->V1 = inf,经由V3中转之后V2->V3->V1 = 10, 于是V2到V1的最短距离变化为10,更新路由矩阵R(2,1) = R(2,3) = 3。

V2->V3 = 3

V2->V4 = inf,经由V3中转之后V2->V3->V4 = 4, 于是V2到V5的最短距离变化为4,更新路由矩阵R(2,4) = R(2,3) = 3。

V3->V1 = 7

V3->V2 = 9

V3->V4 = 1

V4->V1 = 5

V4->V2 = 7

V4->V3 = 10

于是现在的距离矩阵和路由矩阵可以变为:


最短路径-Floyd算法的matlab实现.md「建议收藏」
最短路径-Floyd算法的matlab实现.md「建议收藏」

现在假设在从V1中转的基础上,图中的每个点之间还可以经由V4中转,于是:

V1->V2 = 2

V1->V3 = 5

V1->V4 = 4

V2->V1 = 10,经由V4中转之后V2->V4->V1 = 9, 于是V3到V1的最短距离变化为9,更新路由矩阵R(2,1) = R(2,4) = 3。

V2->V3 = 3

V2->V4 = 4

V3->V1 = 7,经由V4中转之后V3->V4->V1 = 6, 于是V3到V1的最短距离变化为6,更新路由矩阵R(3,1) = R(3,4) = 4。

V3->V2 = 9,经由V4中转之后V3->V4->V2 = 8, 于是V3到V1的最短距离变化为8,更新路由矩阵R(3,2) = R(3,4) = 4。

V3->V4 = 1

V4->V1 = 5

V4->V2 = 7

V4->V3 = 10

于是现在的距离矩阵和路由矩阵可以变为:


最短路径-Floyd算法的matlab实现.md「建议收藏」
最短路径-Floyd算法的matlab实现.md「建议收藏」

好了,到此所有点都中转过了,任意两点之间的最短距离就是最后距离矩阵中的数据,那么其路径该怎么表示呢?路径全部记录在路由矩阵中了,我们只要读取路由矩阵就可以了。

举个例子:v4->V3

从距离矩阵中可以看出V4->V3的最短距离是D(4,3) = 10;根据其路由矩阵我们可以看出:

R(4,3) = 1,表示V4->V3,先经过V1,于是再看R(1,3) = 2,表示还需要再经过V2,于是我们看R(2,3) = 3,这个时候我们发现终于到了V3,所以我们梳理一下,V4->V3的最短路径是:V4->V1->V2->V3。简言之就是固定列,根据路由矩阵在行中跳转,直到跳转到对应的点。

所以最后我们展示出代码就很容易理解了:

% floyd.m
% 采用floyd算法计算图a中每对顶点最短路
% d是矩离矩阵
% r是路由矩阵
function [d,r]=floyd(a)
n=size(a,1);
% 初始化距离矩阵
d=a;
% 初始化路由矩阵
for i=1:n
    for j=1:n
        r(i,j)=j;
    end 
end 
r;

% Floyd算法开始
for k=1:n
    for i=1:n
        for j=1:n
            if d(i,k)+d(k,j)<d(i,j)
                d(i,j)=d(i,k)+d(k,j);
                r(i,j)=r(i,k);
            end 
        end 
    end
    k;
    d;
    r;
end
d
r

最后我还写了一个用于打印路径的函数:

% DisplayPath.m 打印路径函数
function DisplayPath(route, start, dest)
  % 打印出任意两点之间的最短路径 
  % route : 路由表 
  % start : 起点index
  % dest : 终点index
  
  i = 1;
  
  while 1
    if(route(start, dest) ~= dest)
      fprintf('V%s -> ', num2str(start));
      start = route(start, dest);
    else
      fprintf('V%s -> ', num2str(start));
      fprintf('V%s\n', num2str(dest));
      break;
    end
  end

我将上面的举例的图使用floyd算法进行计算,并最后打印出任意两点之间的最短路径:

a = [0 2 6 4;
    inf 0 3 inf;
    7 inf 0 1 ;
    5 inf 12 0];
    
[d,r]=floyd(a)


disp('--------------------------')

for i = 1 : 4
  for j = 1 : 4
   DisplayPath(r, i, j);
  end
end

运行结果为:

main

d =

 0     2     5     4
 9     0     3     4
 6     8     0     1
 5     7    10     0

r =

 1     2     2     4
 3     2     3     3
 4     4     3     4
 1     1     1     4

V1 -> V1
V1 -> V2
V1 -> V2 -> V3
V1 -> V4
V2 -> V3 -> V4 -> V1
V2 -> V2
V2 -> V3
V2 -> V3 -> V4
V3 -> V4 -> V1
V3 -> V4 -> V1 -> V2
V3 -> V3
V3 -> V4
V4 -> V1
V4 -> V1 -> V2
V4 -> V1 -> V2 -> V3
V4 -> V4

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/152199.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月22日 上午6:16
下一篇 2022年6月22日 上午6:36


相关推荐

  • Java 单例模式[通俗易懂]

    Java 单例模式[通俗易懂]单例模式(SingletonPattern)是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。注意:1、单例类只能有一个实例。 2、单例类必须自己创建自己的唯一实例。 3、单例类必须给所有其他对象提供这一实例。…

    2022年7月9日
    22
  • FRP 内网穿透下载配置[通俗易懂]

    FRP 内网穿透下载配置[通俗易懂]FRP内网穿透下载配置Frp服务的建造下载:修改配置文件frps.ini(服务端)配置文件解释说明:frpc.ini(客户端)配置文件解释说明:启动服务配置启动:创建server端服务脚本:(centos6)创建客户端服务脚本:公网服务器端:CentOS6防火墙配置文件位置CentOS7防火墙配置文件位置联系我Frp服务的建造搭建FRP很简单,关键的步骤只有三步:1,获取FRP文件;2,设置FRP配置文件;3,启动FRP服务。下载:下载地址:https://github.com/

    2025年11月8日
    7
  • AIGC AI绘画 Midjourney 的详细使用手册

    AIGC AI绘画 Midjourney 的详细使用手册

    2026年3月15日
    3
  • Windows10系统怎么查看硬盘格式_Win10磁盘管理MBR与GPT区分

    Windows10系统怎么查看硬盘格式_Win10磁盘管理MBR与GPT区分

    2026年3月16日
    3
  • 智谱开源GLM-ASR-Nano-2512模型推动端侧AI普及!

    智谱开源GLM-ASR-Nano-2512模型推动端侧AI普及!

    2026年3月12日
    2
  • Python关键字及其含义

    Python关键字及其含义关键字含义 False 布尔类型的值 表示假 与 True 相对 None 表示什么也没有 自己的数据类型 NoneTypeTrue 布尔类型的值 表示真 与 False 相反 and 用于表达式运算 逻辑与操作 as 用于类型转换 assert 断言 用于判断变量或者条件表达式的值是否为真 break 中断循环语句的执行 class 用于定义类 cont

    2026年3月18日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号