弗洛伊德算法(Floyd-Warshall Algorithm),跟克鲁斯卡尔算法一样是为了解决给定加权图中某一个顶点到其他顶点间的最短距离,可以处理有向图或负权的最短路径问题,同时也被用于在计算有向图的传递闭关。该算法已创始人之一,1978年图领奖获得者,斯坦福大学计算机教授罗伯特·弗洛伊德。
适用范围:无负权回路即可,边权正负都可以,运行一次算法即可得到任意两点之间的最短路径。
Floyd算法适用于APSP(AllPairsShortestPaths),是一种动态规划算法,稠密图效果最佳,边权可正可负。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率高于Dijkstra算法。
初始化dis邻接矩阵和前驱节点矩阵,前驱节点初始化的时候在还未访问任何节点的时候前驱节点为自身 如A点在还未访问BCDEFG的时候前驱节点都是A
三层for循环交叉,分别假定为起点,中间节点,终点遍历所有情况
例如以A为起点的情况下,经过分别以ABCDEFG为中间节点,到终点ABCEDFG的情况都考虑到
起点 | A,B,C,D,E,F,G |
---|---|
中间节点 | A,B,C,D,E,F,G |
终点 | A,B,C,D,E,F,G |
完成所有循环之后即可得到每一个点到其他另外所有点的最短距离,循环的过程中不断更新dis数组,可以不断更新原本不直连的距离,如原本AD节点原本不连接,在A循环之后计算出了AB的距离,在以B为中间节点时可以到达D,可以计算出BD距离,从而可以计算出AD的距离,再不断的循环中可以有会AD线路更短的距离会继续更新
A, B, C , D, E, F 六个村庄
3)计算从任意一个村庄出发到其它村庄的最短距离是多少?
class FloydAlgorithm(object):
def __init__(self, vertexes, edges):
self.vertexes = vertexes
self.edges = edges
self.pre = [[i for _ in range(len(self.vertexes))] for i in range(len(self.vertexes))]
# 初始化到各节点之间的距离为无限大
# self.dis = [[float('inf') for i in range(len(self.vertexes))] for _ in range(len(self.vertexes))]
# for i in range(len(self.dis)):
# for j in range(len[i]):
# if i == j:
# self.dis[i][j] = 0
def floyd(self):
length = float('inf')
for i in range(len(self.vertexes)):
# 起点
for k in range(len(self.vertexes)):
# 中间点
for j in range(len(self.vertexes)):
# 直连
i_j = self.edges[i][j]
# 经过k
i_k_j = self.edges[i][k] + self.edges[k][j]
if i_k_j < i_j:
self.edges[i][j] = i_k_j
self.pre[i][j] = self.pre[k][j]
def show(self):
for item in self.edges:
print(item)
print('=' * 20)
for item in self.pre:
print(item)
if __name__ == '__main__':
vertex = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
N = float('inf')
mertix = [
[0, 5, 7, N, N, N, 2],
[5, 0, N, 9, N, N, 3],
[7, N, 0, N, 8, N, N],
[N, 9, N, 0, N, 4, N],
[N, N, 8, N, 0, 5, 4],
[N, N, N, 4, 5, 0, 6],
[2, 3, N, N, 4, 6, 0],
]
floyd_algorithm = FloydAlgorithm(vertex, mertix)
floyd_algorithm.floyd()
floyd_algorithm.show()