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

最短路径-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如下:

上面是初始的距离矩阵和路由矩阵,现在我们假设:**图中的每个点之间可以经由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

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

现在假设在从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。

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

现在假设在从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

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

现在假设在从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

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

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

举个例子: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

  • 156
    点赞
  • 599
    收藏
    觉得还不错? 一键收藏
  • 39
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 39
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值