图-弗洛伊德FloydWarshall算法介绍
图-弗洛伊德(Floyd-Warshall)算法是一种计算图中所有顶点对之间最短路径的动态规划算法。该算法可以处理包含正权、负权(但不包括负权环)的有向图或无向图。下面是对Floyd-Warshall算法的详细解释:
算法步骤
初始化:
创建一个二维数组dist[V][V](V是图中顶点的数量),其中dist[i][j]表示从顶点i到顶点j的直接距离。
如果顶点i和顶点j之间有直接连接的边,则dist[i][j]为边的权重;否则,dist[i][j]设为无穷大(或图中的一个足够大的数,表示两点间不可达)。
对于所有顶点i,dist[i][i]应初始化为0(表示到自身的距离为0)。
三重循环遍历:
外层循环遍历所有中间点k(k从1到V)。
中间循环和内层循环分别遍历所有的起点i和终点j(i和j也都从1到V)。
对于每一对(i, j),检查是否存在一个更短的路径,即经过点k的路径是否比已知的dist[i][j]更短。这通过比较dist[i][k] + dist[k][j]和dist[i][j]来实现。
如果dist[i][k] + dist[k][j] < dist[i][j],则更新dist[i][j] = dist[i][k] + dist[k][j]。
结果:
算法结束后,dist[i][j]将包含从顶点i到顶点j的最短路径的长度。
时间复杂度
Floyd-Warshall算法的时间复杂度为O(V^3),其中V是图中顶点的数量。这是因为算法中使用了三重嵌套循环来遍历所有可能的顶点对和中间点。
示例代码(Python)
def floyd_warshall(graph):
V = len(graph)
dist = list(map(lambda i: list(map(lambda j: j, i)), graph))
for k in range(V):
for i in range(V):
for j in range(V):
if dist[i][k] + dist[k][j] < dist[i][j]:
dist[i][j] = dist[i][k] + dist[k][j]
return dist
# 示例图的邻接矩阵表示(无穷大用float('inf')表示)
graph = [
[0, 5, float('inf'), 10],
[float('inf'), 0, 3, float('inf')],
[float('inf'), float('inf'), 0, 1],
[float('inf'), float('inf'), float('inf'), 0]
]
# 计算所有顶点对之间的最短路径
dist = floyd_warshall(graph)
# 打印结果
for row in dist:
print(row)
注意事项
Floyd-Warshall算法可以处理负权边,但不能处理负权环。
对于大型图或稀疏图,其他算法(如Dijkstra算法结合优先队列或Bellman-Ford算法)可能更高效。
在实际应用中,如果只需要计算单个源点到所有其他点的最短路径,则使用Dijkstra算法可能更合适。
图-弗洛伊德FloydWarshall算法python实现样例
以下是Python实现图的弗洛伊德(Floyd-Warshall)算法的示例代码:
# 定义一个表示无穷大的常量
INF = float('inf')
def floydWarshall(graph):
"""
Floyd-Warshall算法的实现
:param graph: 图的邻接矩阵表示
:return: 所有顶点之间的最短路径长度矩阵
"""
# 复制邻接矩阵,避免直接修改原始矩阵
dist = [row[:] for row in graph]
n = len(graph)
# 对于每个顶点k,尝试经过它的路径,更新最短路径矩阵
for k in range(n):
for i in range(n):
for j in range(n):
if dist[i][k] != INF and dist[k][j] != INF and dist[i][k] + dist[k][j] < dist[i][j]:
dist[i][j] = dist[i][k] + dist[k][j]
return dist
# 测试代码
# 创建一个邻接矩阵表示的图
graph = [
[0, 5, INF, 10],
[INF, 0, 3, INF],
[INF, INF, 0, 1],
[INF, INF, INF, 0]
]
# 调用Floyd-Warshall算法计算最短路径长度矩阵
shortestPaths = floydWarshall(graph)
# 打印最短路径长度矩阵
for row in shortestPaths:
print(row)
输出结果:
[0, 5, 8, 9]
[inf, 0, 3, 4]
[inf, inf, 0, 1]
[inf, inf, inf, 0]
这个示例中,我们定义了一个邻接矩阵graph
,表示一个有向图。通过调用floydWarshall
函数,我们可以获取所有顶点之间的最短路径长度矩阵shortestPaths
。然后,我们通过遍历该矩阵,打印出最短路径长度矩阵的每一行,即可得到最终结果。