最短路问题之Floyd算法

本文探讨了最短路问题中的Floyd算法,详细解释了算法步骤,并通过Python和Matlab代码实例展示了如何求解图中各点间的最短距离。
摘要由CSDN通过智能技术生成

最短路性质

在图 G G G中,记 ( v i , v j ) k (v_i,v_j)_k (vi,vj)k为点 v i , v j v_i, v_j vi,vj之间的第 k k k条路径, ∣ ( v i , v j ) k ∣ |(v_i,v_j)_k| (vi,vj)k为点 v i , v j v_i, v_j vi,vj之间沿着第 k k k条路径的权和。设从点 v 0 v_0 v0到点 v n v_n vn之间的最短路径 ( v 0 , v n ) k 0 (v_0,v_n)_{k_0} (v0,vn)k0
v 0 → . . . → v n , v_0 \rightarrow ... \rightarrow v_n, v0...vn, v i , v j v_i, v_j vi,vj是路径中的两点,则有
∣ ( v i , v j ) k 0 ∣ = min ⁡ ∀ k ∣ ( v i , v j ) k ∣ , |(v_i, v_j)_{k_0}| = \min_{\forall k}|(v_i, v_j)_k|, (vi,vj)k0=kmin(vi,vj)k,即最短路的任一段也是最短路。

算法步骤

在这里插入图片描述

例题

求出图中各点之间的最短距离。
在这里插入图片描述

Python代码

import numpy as np
from numpy import inf

# 输入带权距离矩阵
W = np.array([
    [0, 5, 2, inf, inf, inf, inf],
    [5, 0, inf, 2, 7, inf, inf],
    [2, inf, 0, 7, 0, 4, inf],
    [inf, 2, 7, 0, 6, 2, inf],
    [inf, 7, inf, 6, 0, 1, 3],
    [inf, inf, 4, 2, 1, 0, 7],
    [inf, inf, inf, inf, 3, 6, 0]
])

# 计算顶点数
N = W.shape[0]

# 给最短距离矩阵赋初值
D_iter = W

# 给路径矩阵赋初值
R_iter = np.zeros([N, N]).astype('int')
for i in range(N):
    R_iter[i, :] = list(range(N))

# 算法迭代主体
for k_iter in range(N):
    D_new = D_iter
    for i in range(N):
        for j in range(N):
            t = D_iter[i, k_iter] + D_iter[k_iter, j]
            if t < D_iter[i, j]:
                D_new[i, j] = t
                R_iter[i, j] = k_iter
    D_iter = D_new
    k_iter += 1

# 输出最短距离矩阵和相应的路径矩阵
print('D(', N, ')=')
print(D_iter)
print('R(', N, ')=')
print(R_iter)

# 打印出最短路径和相应的距离
for i in range(N):
    for j in range(N):
        # 提取点i到点j的最短距离
        dist = D_iter[i, j]

        # 计算点i到点j的最短路径
        if R_iter[i, j] == j:
            path = [i, j]
        else:
            k = R_iter[i, j]
            path_1 = [k]
            while R_iter[i, k] != k:
                k = R_iter[i, k]
                path_1 = [k] + path_1

            k = R_iter[i, j]
            path_2 = []
            while R_iter[k, j] != j:
                k = R_iter[k, j]
                path_2.append(k)

            path = [i] + path_1 + path_2 + [j]

        # 打印相应信息
        print(i + 1, '到', j + 1, '的最短路径为:', path, '长度为:', dist)

  结果:

D( 7 )=
[[ 0.  5.  2.  5.  2.  3.  5.]
 [ 5.  0.  7.  2.  5.  4.  8.]
 [ 2.  5.  0.  3.  0.  1.  3.]
 [ 7.  2.  6.  0.  3.  2.  6.]
 [ 7.  5.  5.  3.  0.  1.  3.]
 [ 6.  4.  4.  2.  1.  0.  4.]
 [10.  8.  8.  6.  3.  4.  0.]]
R( 7 )=
[[0 1 2 5 2 4 4]
 [0 1 0 3 5 3 5]
 [0 5 2 5 4 4 4]
 [1 1 5 3 5 5 5]
 [5 5 5 5 4 5 6]
 [2 3 2 3 4 5 4]
 [5 5 5 5 4 4 6]]
11 的最短路径为: [0, 0] 长度为: 0.0
12 的最短路径为: [0, 1] 长度为: 5.0
13 的最短路径为: [0, 2] 长度为: 2.0
14 的最短路径为: [0, 2, 4, 5, 3] 长度为: 5.0
15 的最短路径为: [0, 2, 4] 长度为: 2.0
16 的最短路径为: [0, 2, 4, 5] 长度为: 3.0
17 的最短路径为: [0, 2, 4, 6] 长度为: 5.0
21 的最短路径为: [1, 0] 长度为: 5.0
22 的最短路径为: [1, 1] 长度为: 0.0
23 的最短路径为: [1, 0, 2] 长度为: 7.0
24 的最短路径为: [1, 3] 长度为: 2.0
25 的最短路径为: [1, 3, 5, 4] 长度为: 5.0
26 的最短路径为: [1, 3, 5] 长度为: 4.0
27 的最短路径为: [1, 3, 5, 4, 6] 长度为: 8.0
31 的最短路径为: [2, 0] 长度为: 2.0
32 的最短路径为: [2, 4, 5, 3, 1] 长度为: 5.0
33 的最短路径为: [2, 2] 长度为: 0.0
34 的最短路径为: [2, 4, 5, 3] 长度为: 3.0
35 的最短路径为: [2, 4] 长度为: 0.0
36 的最短路径为: [2, 4, 5] 长度为: 1.0
37 的最短路径为: [2, 4, 6] 长度为: 3.0
41 的最短路径为: [3, 1, 0] 长度为: 7.0
42 的最短路径为: [3, 1] 长度为: 2.0
43 的最短路径为: [3, 5, 2] 长度为: 6.0
44 的最短路径为: [3, 3] 长度为: 0.0
45 的最短路径为: [3, 5, 4] 长度为: 3.0
46 的最短路径为: [3, 5] 长度为: 2.0
47 的最短路径为: [3, 5, 4, 6] 长度为: 6.0
51 的最短路径为: [4, 5, 2, 0] 长度为: 7.0
52 的最短路径为: [4, 5, 3, 1] 长度为: 5.0
53 的最短路径为: [4, 5, 2] 长度为: 5.0
54 的最短路径为: [4, 5, 3] 长度为: 3.0
55 的最短路径为: [4, 4] 长度为: 0.0
56 的最短路径为: [4, 5] 长度为: 1.0
57 的最短路径为: [4, 6] 长度为: 3.0
61 的最短路径为: [5, 2, 0] 长度为: 6.0
62 的最短路径为: [5, 3, 1] 长度为: 4.0
63 的最短路径为: [5, 2] 长度为: 4.0
64 的最短路径为: [5, 3] 长度为: 2.0
65 的最短路径为: [5, 4] 长度为: 1.0
66 的最短路径为: [5, 5] 长度为: 0.0
67 的最短路径为: [5, 4, 6] 长度为: 4.0
71 的最短路径为: [6, 4, 5, 2, 0] 长度为: 10.0
72 的最短路径为: [6, 4, 5, 3, 1] 长度为: 8.0
73 的最短路径为: [6, 4, 5, 2] 长度为: 8.0
74 的最短路径为: [6, 4, 5, 3] 长度为: 6.0
75 的最短路径为: [6, 4] 长度为: 3.0
76 的最短路径为: [6, 4, 5] 长度为: 4.0
77 的最短路径为: [6, 6] 长度为: 0.0

Matlab代码

%% 无向图的带权邻接矩阵
D=[
    0 5 2 inf inf inf inf
    5 0 inf 2 7 inf inf
    2 inf 0 7 0 4 inf
    inf 2 7 0 6 2 inf
    inf 7 inf 6 0 1 3
    inf inf 4 2 1 0 7
    inf inf inf inf 3 6 0
    ];

R_iter=[];
for i=1:length(D)
    R_iter = [R_iter;1:length(D)];
end
D_iter = D;
k = 1;
while k <= length(D)
    D_new = D_iter;
    for i=1:length(D)
        for j=1:length(D)
            t = D_iter(i,k)+D_iter(k,j);
            if t < D_iter(i,j)
                D_new(i,j) = t;
                R_iter(i,j) = k;
            end
        end
    end
    D_iter = D_new;
    k = k+1;
end
disp(['D(',num2str(k-1),')='])
disp(D_iter)  % 打印点到点最短距离矩阵
disp(['R(',num2str(k-1),')='])
disp(R_iter)  % 打印路径矩阵

%% 打印出最短路径和相应的距离
for i=1:length(D)
    for j=1:length(D)
        dist = D_iter(i,j);
        if R_iter(i,j) == j
            path = [i,j];
        else
            k = R_iter(i,j);
            path_1 = [k]; 
            while R_iter(i,k) ~= k
                k = R_iter(i,k);
                path_1 = [k, path_1];
            end
            k = R_iter(i,j);
            path_2 = [];
            while R_iter(k,j) ~= j
                k = R_iter(k,j);
                path_2 = [path_2, k];
            end
            path = [i, path_1, path_2, j];
        end
        disp([num2str(i),'到',num2str(j),'的最短路为',...
            num2str(path),' 长度为',num2str(dist)])
    end
end

  结果:

D(7)=
     0     5     2     5     2     3     5
     5     0     7     2     5     4     8
     2     5     0     3     0     1     3
     7     2     6     0     3     2     6
     7     5     5     3     0     1     3
     6     4     4     2     1     0     4
    10     8     8     6     3     4     0
R(7)=
     1     2     3     6     3     5     5
     1     2     1     4     6     4     6
     1     6     3     6     5     5     5
     2     2     6     4     6     6     6
     6     6     6     6     5     6     7
     3     4     3     4     5     6     5
     6     6     6     6     5     5     7
11的最短路为1  1 长度为0
12的最短路为1  2 长度为5
13的最短路为1  3 长度为2
14的最短路为1  3  5  6  4 长度为5
15的最短路为1  3  5 长度为2
16的最短路为1  3  5  6 长度为3
17的最短路为1  3  5  7 长度为5
21的最短路为2  1 长度为5
22的最短路为2  2 长度为0
23的最短路为2  1  3 长度为7
24的最短路为2  4 长度为2
25的最短路为2  4  6  5 长度为5
26的最短路为2  4  6 长度为4
27的最短路为2  4  6  5  7 长度为8
31的最短路为3  1 长度为2
32的最短路为3  5  6  4  2 长度为5
33的最短路为3  3 长度为0
34的最短路为3  5  6  4 长度为3
35的最短路为3  5 长度为0
36的最短路为3  5  6 长度为1
37的最短路为3  5  7 长度为3
41的最短路为4  2  1 长度为7
42的最短路为4  2 长度为2
43的最短路为4  6  3 长度为6
44的最短路为4  4 长度为0
45的最短路为4  6  5 长度为3
46的最短路为4  6 长度为2
47的最短路为4  6  5  7 长度为6
51的最短路为5  6  3  1 长度为7
52的最短路为5  6  4  2 长度为5
53的最短路为5  6  3 长度为5
54的最短路为5  6  4 长度为3
55的最短路为5  5 长度为0
56的最短路为5  6 长度为1
57的最短路为5  7 长度为3
61的最短路为6  3  1 长度为6
62的最短路为6  4  2 长度为4
63的最短路为6  3 长度为4
64的最短路为6  4 长度为2
65的最短路为6  5 长度为1
66的最短路为6  6 长度为0
67的最短路为6  5  7 长度为4
71的最短路为7  5  6  3  1 长度为10
72的最短路为7  5  6  4  2 长度为8
73的最短路为7  5  6  3 长度为8
74的最短路为7  5  6  4 长度为6
75的最短路为7  5 长度为3
76的最短路为7  5  6 长度为4
77的最短路为7  7 长度为0
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

此账号已停更

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值