329. 矩阵中的最长递增路径c_图的最短路径Floyd算法

昨天说了一种图的最短路径求解算法Dijkstra,这个算法是专注于求某一个点出发,到所有节点的最短距离和最短路径。那如果我想知道所有节点到其他节点的最短路径怎么办?

很简单,就对每一个节点做一次Dijkstra算法就可以了。因为Dijkstra算法的复杂度是那再遍历一下所有个节点,复杂度就是。

今天咱们再来说一个算法,也是求所有节点到其他节点最短路径的算法,算法复杂度也是。虽然算法复杂度并没有降低,但是代码却比Dijkstra简洁了太多,这就是Floyd算法。Floyd简洁的代码下,有着不一样的思考方式。

553e3736280286e8fccfa26bb5947cb0.png

Dijkstra得到最短路径的方法比较的直觉,就是从一个点出发,然后遍历所有的点,找到起点到达不同点的路径。而Floyd的思路不太一样,他相当于是一直在尝试,如果在两个节点之间插入一个中转节点,距离会不会更短。

首先我们尝试,如果所有的节点对都从A节点中转,那么节点之间的距离会不会更短呢?于是我们就需要比较,B-C的距离和B-A-C之间的距离,如果更短,就更新B-C之间的最短距离,然后更新最短路径节点。这说明,通过中间节点,B-C之间的距离更短了,找到了一条新的B-C之间的最短路径。用此方法看完所有的节点对,看看是不是能够发现更短的路径。

A节作为中转节点遍历了一遍,然后再试试一下在两个节点中插入一个中转节点B,用同样的方法更新一遍所有节点对的最短距离。

依次类推,把所有的节点都作为中转节点更新一下最短路径之后,我们就得到了一个矩阵,记录着各个节点到达其他节点的最短路径。

Floyd的代码实现非常简洁,简洁到一目了然,可以看一下这个代码实现。

# Floyd最短路径算法def sp_floyd(graph_matrix):    # 初始距离矩阵    dis_matrix = graph_matrix.copy()    # 最短路径矩阵,初始值都为-1    path_matrix = np.ones((len(graph_matrix),len(graph_matrix)))*(-1)    # 遍历每一个中间节点    for k in range(len(graph_matrix)):        # 遍历每一个起始节点        for i in range(len(graph_matrix)):            # 遍历每一个截止节点            for j in range(len(graph_matrix)):                if dis_matrix[i][j] > (dis_matrix[i][k] + dis_matrix[k][j]):                    dis_matrix[i][j] = dis_matrix[i][k] + dis_matrix[k][j]                    path_matrix[i][j] = k                        print("最短距离:", dis_matrix)    print("最短路径:", path_matrix)

只要完成三次遍历,就可以得到所有节点之间的最短路径了。

最后看一下演示的示例。

# 构建如图1的邻接矩阵,INFINITY为一个很大很大的常数。graph_matrix = np.array([[0, 10, INFINITY, INFINITY, INFINITY, 11, INFINITY, INFINITY,INFINITY],                         [10, 0, 18, INFINITY, INFINITY, INFINITY, 16, INFINITY, 12],                         [INFINITY, 18, 0, 22, INFINITY, INFINITY, INFINITY, INFINITY, 8],                         [INFINITY, INFINITY, 22, 0, 20, INFINITY, 24, 16, 21],                         [INFINITY, INFINITY, INFINITY, 20, 0, 26, INFINITY, 7,INFINITY],                         [11, INFINITY, INFINITY, INFINITY, 26, 0, 17, INFINITY,INFINITY],                         [INFINITY, 16, INFINITY, 24, INFINITY, 17, 0, 19,INFINITY],                         [INFINITY, INFINITY, INFINITY, 16, 7, INFINITY, 19, 0,INFINITY],                         [INFINITY, 12, 8, 21, INFINITY, INFINITY, INFINITY, INFINITY,0]])# 图节点名称vex_list = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']print('节点:',vex_list)# 使用Floyd算法,打印图中的最短距离矩阵和最短路径矩阵sp_floyd(graph_matrix)

结果如下

节点: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']最短距离:[[ 0 10 28 43 37 11 26 44 22] [10  0 18 33 42 21 16 35 12] [28 18  0 22 42 39 34 38  8] [43 33 22  0 20 41 24 16 21] [37 42 42 20  0 26 26  7 41] [11 21 39 41 26  0 17 33 33] [26 16 34 24 26 17  0 19 28] [44 35 38 16  7 33 19  0 37] [22 12  8 21 41 33 28 37  0]]最短路径:[[-1. -1.  1.  8.  5. -1.  1.  5.  1.] [-1. -1. -1.  8.  7.  0. -1.  6. -1.] [ 1. -1. -1. -1.  3.  1.  1.  3. -1.] [ 8.  8. -1. -1. -1.  6. -1. -1. -1.] [ 5.  7.  3. -1. -1. -1.  7. -1.  3.] [-1.  0.  1.  6. -1. -1. -1.  4.  1.] [ 1. -1.  1. -1.  7. -1. -1. -1.  1.] [ 5.  6.  3. -1. -1.  4. -1. -1.  3.] [ 1. -1. -1. -1.  3.  1.  1.  3. -1.]]

END

6ff7d6b45ec9fa550552db49b6232db1.png

作者:锅哥不姓郭

   图片:网络(侵删)

da6d5cf8f3557a6c7d5ab0c6442d1103.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值