Matlab实现Floyd最短路径算法并计算路径链

问:如何计算出Floyd最短路径算法中的路径链?
程序猿答疑:
最近看了网上一些Floyd最短路径算法的实现,在求出最短路径的距离矩阵和路径矩阵后如果需要具体列出某两点之间的路径都是用路径矩阵动态打打印的,没有保存到具体的数据结构中。今天程序员答疑给大家演示下如何用Matlab语言实现Floyd最短路径算法并计算路径链,路径链保存在列表中,在Matlab中的形式为一个1*n的矩阵。

Floyd算法

6个点距离图
如上图,6个点A1、A2、A3、A4、A5、A6,点与点之间连线上的数字表示两点间的距离,如A1到A2的距离为5,点与点之间没有直接连线表示两点之间不能直达,可通过其他点作为中间点形成通路,如A1到A3没有直达路径,但从A1出发可以先到A2,再从A2到A3,这条路径的长度为9(A1到时A2距离为5,A2到A3距离为4,两者之和为9)。我们把6个点每2个点之间的连线距离填写在一个邻接矩阵a中,矩阵的i行j列上的数字a[i][j]为A[i]点与A[j]点的直接连线距离。如果两点之间没有直接连线,直达距离为无穷大,用inf表示(inf在Matlab中表示无穷大),同一点与自身的距离为0。上图中的a矩阵为

a=[
 0 5 inf 8 6 6;
 5 0 4 9 inf inf;
 inf 4 0 inf inf 10;
 8 9 inf 0 1 inf;
 6 inf inf 1 0 3;
 6 inf 10 inf 3 0]

为叙述方便,程序员答疑直接用Matlab中的矩阵形式表示矩阵(带分号“;”)。我们可以看到,邻接矩阵是一个对称矩阵,即第i行第j列上的数字与第j行第i列的数字相同,即a[i][j]=a[j][i],这是因为A[i]点与A[j]点的连线距离就是A[j]点与A[i]点的连线距离;同时可以观察到邻接矩阵上的主对角线上的数字a[i][i]为0,即A[i]点到A[i]点的距离记为0(在一个二维的数字矩阵中,从左上角至右下角的对角线为主对角线,从右上角至左下角的对角线为次对角线)。
Floyd算法的输出为最短距离矩阵d和路由矩阵p,最短距离矩阵d的第i行第j列数值d[i][j]表示A[i]点到A[j]点的最短路径长度,路由矩阵p的第i行第j列数值p[i][j](假设为k)表示A[i]点到A[j]点的最短路径由A[i]点到A[k]点的连线和A[k]点到A[j]点的最短路径组合而成,如果k=j,A[k]点到A[j]的最短路径长度为0。最短距离矩阵d初始设置为与邻接矩阵a相同,路由矩阵p初始设置为每列上的数值与列序号相同。两个矩阵初始值的含义为两个点的最短距离初始化为两点的直接连线长度,最短路径为两点间的直接连线(若无直接连线仍认为距离为无穷大)。比如p[2][3]的值为3,即A2点到A3点的最短路径由A2点到A3点的连线和A3点到A3点的最短路径组合而成,A3点到A3点的最短路径长度为0,即在初始路由矩阵p中,A2点到A3点的最短路径为A2到A3的连线,用A2->A3表示,最短路径长度为4。当然,这和最终结果可能不同,比如初始路由矩阵p中A1点到A4点的最短路径为A1->A4,最短路径长度为8,而实际情况是A1点到A4点的最短路径为A1->A5->A4表示,最短路径长度为7。

d=[
 0 5 inf 8 6 6;
 5 0 4 9 inf inf;
 inf 4 0 inf inf 10;
 8 9 inf 0 1 inf;
 6 inf inf 1 0 3;
 6 inf 10 inf 3 0]
p=[
 1 2 3 4 5 6;
 1 2 3 4 5 6;
 1 2 3 4 5 6;
 1 2 3 4 5 6;
 1 2 3 4 5 6;
 1 2 3 4 5 6]

Floyd算法的思想是对于任意两点A[i]和A[j],如果存在一个点A[k]使得A[i]和A[k]的最短路径长度d[i][k]与A[i]和A[j]的最短路径长度d[k][j]之和小于当前A[i]和[j]和最短路径之和d[i][j],则更新d[i][j]为d[i][k]+d[k][j],并设置p[i][j]=p[i][k],即把路径A[i]到A[j]的A[i]的下一个点由p[i][j]换为路径A[i]到A[k]的A[i]的下一个点p[i][k],具体算法如下(Matlab代码源文件名为floyd.m):

function [d,p]=floyd(a)
n=size(a,1); %测出a矩阵的行数
d=a; %初始化距离矩阵
for i=1:n %初始化路由矩阵
    for j=1:n
        p(i,j)=j; %使路由矩阵p形成初始矩阵(每一列上的数为该列的列序数)
    end 
end 
for k=1:n %开始循环遍历计算(用if语句来比较通过k点中转前后的大小)
    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);
                p(i,j)=p(i,k);
            end 
        end 
    end
end

对于图中6个点的距离数据应用Floyd算法得到

d =0     5     9     7     6     6
     5     0     4     9    10    11
     9     4     0    13    13    10
     7     9    13     0     1     4
     6    10    13     1     0     3
     6    11    10     4     3     0
p =1     2     2     5     5     6
     1     2     3     4     4     1
     2     2     3     2     6     6
     5     2     2     4     5     5
     1     4     6     4     5     6
     1     1     3     5     5     6

矩阵d和p是打印在Matlab命令行窗口的形式,与代码中的矩阵表现形式稍有不同(不带分号“;”)。

路径链

根据矩阵d和p可以得出图中任意两点间的最短路径和最短路径的长度。例如A1到A2的最短路径长度为d[1][2]=5,p[1][2]=2,即A1到A2的最短路径要从A1先到A2,A2已经是终点了,不再继续查找路径,最短路径为A1->A2。又如A2到A6的最短路径长度为d[2][6]=11,p[2][6]=1,即A2到A6的最短路径要从A2先到A1,A2->A1,再看p[1][6]的值为6,A6已经是终点了,不再继续查找路径,最短路径为A1->A2->A6。
上述查找最短路径的方法包含着递归的思想,程序猿答疑用递归算法计算路径链(Matlab代码源文件名为path.m)。

% 计算点i到点j的最短路径链
% path_list 最短路径链列表
function [path_list]=path(p,i,j,path_list)
% 将i添加到路径链列表path_list
path_list=[path_list i];
if i==j
    % fprintf('i==j')
    % i和j相等,查找到路径最后一个点,不再继续查找
else
    % fprintf('i~=j')
    % i和j相等,递归查找点p(i,j)和j之间路径链
    path_list=path(p,p(i,j),j,path_list);
end

打印出图中任意两点间的最短路径链(Matlab代码源文件名为main.m)。

a=[
 0 5 inf 8 6 6;
 5 0 4 9 inf inf;
 inf 4 0 inf inf 10;
 8 9 inf 0 1 inf;
 6 inf inf 1 0 3;
 6 inf 10 inf 3 0]
[d,p]=floyd(a)
% path_list最短路径链列表,初始化为空数组[]
path_list=[];
path_list=path(p,i,j,path_list)
n=size(a,1); %测出a矩阵的行数,即图中点个数
for i=1:n
    for j=1:n
        path_list=[];
        path_list=path(p,i,j,path_list);
        fprintf('A%d到A%d的最短路径为:',i,j)
        [r,c]=size(path_list);
        for k=1:c % 打印路径链
            if k<c
                fprintf('%d->',path_list(k))
            else
                fprintf('%d\n',path_list(k))
            end
        end
    end
end

代码输出结果为:

A1到A1的最短路径为:1
A1到A2的最短路径为:1->2
A1到A3的最短路径为:1->2->3
A1到A4的最短路径为:1->5->4
A1到A5的最短路径为:1->5
A1到A6的最短路径为:1->6
A2到A1的最短路径为:2->1
A2到A2的最短路径为:2
A2到A3的最短路径为:2->3
A2到A4的最短路径为:2->4
A2到A5的最短路径为:2->4->5
A2到A6的最短路径为:2->1->6
A3到A1的最短路径为:3->2->1
A3到A2的最短路径为:3->2
A3到A3的最短路径为:3
A3到A4的最短路径为:3->2->4
A3到A5的最短路径为:3->6->5
A3到A6的最短路径为:3->6
A4到A1的最短路径为:4->5->1
A4到A2的最短路径为:4->2
A4到A3的最短路径为:4->2->3
A4到A4的最短路径为:4
A4到A5的最短路径为:4->5
A4到A6的最短路径为:4->5->6
A5到A1的最短路径为:5->1
A5到A2的最短路径为:5->4->2
A5到A3的最短路径为:5->6->3
A5到A4的最短路径为:5->4
A5到A5的最短路径为:5
A5到A6的最短路径为:5->6
A6到A1的最短路径为:6->1
A6到A2的最短路径为:6->1->2
A6到A3的最短路径为:6->3
A6到A4的最短路径为:6->5->4
A6到A5的最短路径为:6->5
A6到A6的最短路径为:6
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Floyd路径算法是一种经典的算法,用于求解加权图中两个节点之间的最路径。该算法基于动态规划的思想,通过不断更新路径中的节点,逐步求得最路径。下面是Floyd算法MATLAB实现代码 = Floyd(W, start, stop) % start为指定起始结点,stop为指定终止结点 D = W; % 最距离矩阵赋初值 n = length(D); % n为结点个数 P = zeros(n,n); % 路由矩阵赋初值 for i = 1:n for j = 1:n P(i,j) = j; end end 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); P(i,j) = P(i,k); end end end end if nargin ~= 3 errordlg('参数个数输入有误!', 'Warning!') else dis = D(start, stop); % 指定两结点间的最距离 m(1) = start; i = 1; while P(m(i),stop) ~= stop k = i + 1; m(k) = P(m(i),stop); i = i + 1; end m(i + 1) = stop; path = m; % 指定两结点之间的最路径 end end ``` 该代码实现Floyd算法,并输出了最距离矩阵和路径矩阵,以及指定两个节点间的最距离和路径。你可以根据需求调用该函数并传入相应的参数,即可得到所需的结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Floyd算法及其MATLAB实现](https://blog.csdn.net/qq_42916979/article/details/104128709)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值