昨天说了一种图的最短路径求解算法Dijkstra,这个算法是专注于求某一个点出发,到所有节点的最短距离和最短路径。那如果我想知道所有节点到其他节点的最短路径怎么办?
很简单,就对每一个节点做一次Dijkstra算法就可以了。因为Dijkstra算法的复杂度是那再遍历一下所有个节点,复杂度就是。
今天咱们再来说一个算法,也是求所有节点到其他节点最短路径的算法,算法复杂度也是。虽然算法复杂度并没有降低,但是代码却比Dijkstra简洁了太多,这就是Floyd算法。Floyd简洁的代码下,有着不一样的思考方式。
![553e3736280286e8fccfa26bb5947cb0.png](https://i-blog.csdnimg.cn/blog_migrate/9e50e8442b7214fb11d2016d290fc63d.jpeg)
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](https://i-blog.csdnimg.cn/blog_migrate/56a228fb0dfa1d4da9877f974f4b4af8.png)
作者:锅哥不姓郭
图片:网络(侵删)