5 只生成图的高级算法之最短路径算法(Dijkstra和Floyd算法)

在上一篇中,我们讨论了图的表示方法,包括邻接矩阵和邻接表。在理解了如何表示图之后,本篇将介绍图的两种重要的最短路径算法——Dijkstra算法和Floyd算法。我们将探讨它们的基本原理、实现方式以及适用场景,通过示例代码来展示这些算法的具体应用。

最短路径问题概述

最短路径问题是图论中一个重要的研究课题,其目标是找出图中两个节点之间的最短路径。最短路径的定义是指路径的边权重之和最小。最短路径算法应用广泛,包括地图导航、网络路由等。

Dijkstra算法

Dijkstra算法是一种贪心算法,专门用于计算图中某一节点到其他所有节点的最短路径。它适用于边权非负的图。

算法原理

  1. 初始化:设定源节点到自身的距离为0,至其他所有节点的距离为∞,并将所有节点标记为未访问。
  2. 选择节点:从未访问节点中选择距离最近的节点作为当前节点。
  3. 更新距离:对于当前节点的每一个邻接节点,计算从源节点通过当前节点到邻接节点的距离,如果该距离小于已知的距离,则更新之。
  4. 标记节点:标记当前节点为已访问。
  5. 重复步骤:重复步骤2至4,直到所有节点均被访问。

示例代码

以下是使用Python实现Dijkstra算法的简单例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import heapq

def dijkstra(graph, start):
# 创建一个优先队列
queue = []
# 初始化距离字典,设定源节点到自身距离为0,其余为∞
distances = {node: float('infinity') for node in graph}
distances[start] = 0
# 将起始节点加入队列
heapq.heappush(queue, (0, start))

while queue:
current_distance, current_node = heapq.heappop(queue)

if current_distance > distances[current_node]:
continue

for neighbor, weight in graph[current_node].items():
distance = current_distance + weight

if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(queue, (distance, neighbor))

return distances

# 示例图的邻接表表示
graph = {
'A': {'B': 1, 'C': 4},
'B': {'A': 1, 'C': 2, 'D': 5},
'C': {'A': 4, 'B': 2, 'D': 1},
'D': {'B': 5, 'C': 1}
}

print(dijkstra(graph, 'A'))

利用案例

假设我们有一张地图,城市A到城市B的距离为1,A到C的距离为4,B到C的距离为2,B到D的距离为5,C到D的距离为1。运行上面的代码,可以得到从城市A出发到所有其他城市的最短路径长度。

Floyd算法

Floyd算法又称Floyd-Warshall算法,适用于求解所有节点对之间的最短路径,处理的是有向图或无向图,可以处理负权边,但不允许存在负权回路。

算法原理

Floyd算法利用动态规划思想,通过逐步更新路径数组来得到任意两点之间的最短路径。

  1. 初始化:创建一个距离矩阵,若边存在,则初始化为边的权重;若不存在,则设为∞;自己到自己设为0。
  2. 更新矩阵:通过逐步遍历每一个节点k,将其作为中介点,更新任意两点i和j之间的最短路径,更新规则为:
    $$ d[i][j] = min(d[i][j], d[i][k] + d[k][j]) $$
  3. 重复步骤:对每个中介点重复此操作。

示例代码

以下是使用Python实现Floyd算法的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def floyd_warshall(graph):
# 复制图的邻接矩阵
distances = [[float('inf')] * len(graph) for _ in range(len(graph))]

for i in range(len(graph)):
for j in range(len(graph)):
distances[i][j] = graph[i][j] if graph[i][j] != 0 else float('inf')
distances[i][i] = 0 # 自身到自身的距离为0

for k in range(len(graph)):
for i in range(len(graph)):
for j in range(len(graph)):
distances[i][j] = min(distances[i][j], distances[i][k] + distances[k][j])

return distances

# 示例图的邻接矩阵表示(无边则为0)
graph_matrix = [
[0, 1, 4, 0],
[1, 0, 2, 5],
[4, 2, 0, 1],
[0, 5, 1, 0]
]

distance_matrix = floyd_warshall(graph_matrix)
for row in distance_matrix:
print(row)

利用案例

在上述示例中,graph_matrix表示城市之间的直接距离,可以用零表示没有直接连接的城市。运行Floyd算法后,可以得到每对城市之间的最短距离,适合多对计算的需求。

总结

本篇我们探讨了Dijkstra算法和Floyd算法两种常用的最短路径算法。Dijkstra算法通常用于从单个源节点计算到其他所有节点的最短路径,而Floyd算法则适合用于计算任意两节点之间的最短路径。这两种算法在实际应用中各有其适用场景,开发者可以根据需求选择合适的算法。在下一篇中,我们将讨论图的高级算法之最小生成树算法(Kruskal和Prim算法),期待与大家继续探索图算法的奥秘。

5 只生成图的高级算法之最短路径算法(Dijkstra和Floyd算法)

https://zglg.work/datastructure-one/5/

作者

IT教程网(郭震)

发布于

2024-08-11

更新于

2024-08-12

许可协议

分享转发

交流

更多教程加公众号

更多教程加公众号

加入星球获取PDF

加入星球获取PDF

打卡评论