目录
1、Floyd是干嘛的
该算法也称为Floyd算法,Roy-Warshall算法,Roy-Floyd算法或WFI算法。
Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。
Floyd算法可以求出任意两个顶点之间的最短路径。
2、基本思想
用一个二维矩阵表示任意两个顶点之间的距离,初始时,这个矩阵的数据元素的值表示的是两个城市的直达距离,值是无穷大∞则表示没有直达距离。
下面以上图为例 (城市公路图及其邻接矩阵)
注意:直达距离不一定是最短距离
假如当前的距离矩阵为D,现在绕道顶点w,查看顶点u到顶点v之间的距离D[u][v]会不会因为绕道顶点w变得更短。如果更短,则更新D[u][v]=D[u][w]+D[w][v]
例如:上图 0-->2 直达距离为6 但是从0-->1-->2距离为5
6>5
通过Floyd计算图G=(V,E)中各个顶点的最短路径时,需要引入两个矩阵,
矩阵D中的元素a[i][j]表示顶点i(第i个顶点)到顶点j(第j个顶点)的距离。
矩阵P中的元素b[i][j],表示顶点i到顶点j经过了b[i][j]记录的值所表示的顶点。
3、代码如下
# -*- coding: utf-8 -*-
"""
@File : Floyd最短路径算法.py
@author: FxDr
@Time : 2022/10/29 21:59
"""
n = 4
INFINITY = 100000.0 # 假设这是无穷大
# 距离矩阵
D = [[0, 2, 6, 4],
[INFINITY, 0, 3, INFINITY],
[7, INFINITY, 0, 1],
[5, INFINITY, 12, 0]
]
# 路径矩阵
P = [[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
# 初始化路径矩阵,即P[u][v] 记录直达路径uv的终点v前面的顶点u
for u in range(0, n):
for v in range(0, n):
P[u][v] = u
print("初始状态:")
print("距离矩阵为:", *D, sep="\n") # sep = "\n" 表示每个输出元素之间用换行分割
print("路径矩阵为:", *P, sep="\n")
for w in range(0, n):
for u in range(0, n):
for v in range(0, n):
if w != u and w != v and D[u][w] + D[w][v] < D[u][v]:
D[u][v] = D[u][w] + D[w][v]
P[u][v] = P[w][v] # P[w][v] 存放着w,w是经过的点 ,也就说u-->v,经过w这个点,而这个点就是P[u][v]的值
print("排序后:")
print("距离矩阵为:", *D, sep="\n") # sep = "\n" 表示每个输出元素之间用换行分割
print("路径矩阵为:", *P, sep="\n")
输出为:
4、逆推到起点
根据路径矩阵P,对于任何一对顶点u、顶点v,其路径可以从终点倒过来追踪到起点,即终点是v,其前一个顶点是P[u][v],再前一个顶点是P[u][P[u][v]]、....
代码如下
for u in range(0, n):
for v in range(0, n):
if u == v:
continue
print("{}到{}的逆向路径是:".format(u, v), end=' ')
print(v, end=',') # 先输出终点
w = P[u][v] # 推到上一个节点
while w != u:
print(w, end=',')
w = P[u][w] # 推到u-->w的上一个节点
print(u)
输出结果:
5、完整代码
# -*- coding: utf-8 -*-
"""
@File : Floyd最短路径算法.py
@author: FxDr
@Time : 2022/10/29 21:59
"""
n = 4
INFINITY = 100000.0 # 假设这是无穷大
# 距离矩阵
D = [[0, 2, 6, 4],
[INFINITY, 0, 3, INFINITY],
[7, INFINITY, 0, 1],
[5, INFINITY, 12, 0]
]
# 路径矩阵
P = [[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
# 初始化路径矩阵,即P[u][v] 记录直达路径uv的终点v前面的顶点u
for u in range(0, n):
for v in range(0, n):
P[u][v] = u
print("初始状态:")
print("距离矩阵为:", *D, sep="\n") # sep = "\n" 表示每个输出元素之间用换行分割
print("路径矩阵为:", *P, sep="\n")
for w in range(0, n):
for u in range(0, n):
for v in range(0, n):
if w != u and w != v and D[u][w] + D[w][v] < D[u][v]:
D[u][v] = D[u][w] + D[w][v]
P[u][v] = P[w][v] # P[w][v] 存放着w,w是经过的点 ,也就说u-->v,经过w这个点,而这个点就是P[u][v]的值
print("排序后:")
print("距离矩阵为:", *D, sep="\n") # sep = "\n" 表示每个输出元素之间用换行分割
print("路径矩阵为:", *P, sep="\n")
for u in range(0, n):
for v in range(0, n):
if u == v:
continue
print("{}到{}的逆向路径是:".format(u, v), end=' ')
print(v, end=',') # 先输出终点
w = P[u][v] # 推到上一个节点
while w != u:
print(w, end=',')
w = P[u][w] # 推到u-->w的上一个节点
print(u)