Dijkstra算法(模板)--python实现
Dijkstra算法是一种用于解决单源最短路径问题的经典算法,其目标是找到图中从一个源节点到所有其他节点的最短路径。
下面我将详细介绍Dijkstra算法
动图展示(取自:https://blog.csdn.net/qq_62789540/article/details/126044970?spm=1001.2014.3001.5506)

算法步骤:
-
初始化: 设置一个起始节点,将其距离设置为0,其他节点的距离设置为无穷大(或者一个极大的数),并将所有节点标记为未访问。
-
选择下一个节点: 从未访问的节点中选择距离起始节点最近的节点作为当前节点。
-
更新距离: 对于当前节点的所有邻居节点,更新其到起始节点的距离。如果通过当前节点到达邻居节点的距离比当前已知的距离更短,则更新邻居节点的距离。
-
标记节点: 将当前节点标记为已访问。
-
重复步骤2-4: 重复执行步骤2到步骤4,直到所有节点都被标记为已访问。
-
输出结果: 当所有节点都被标记为已访问时,算法结束,输出从起始节点到每个节点的最短距离。
示例图表:
假设我们有以下图表表示的图,其中节点之间的边代表路径,边上的数字代表路径的权重或距离。
4 1
(A) ----- (B) ----- (C)
| \ / | / |
| \ 2 / | 5 / |
|3 \(D) | / 3 |
| \ | / \|
| \ | / (F)
| \ | / |
|_______\| /_________|
6 6 2
5 7
现在我们以节点A作为起点运行Dijkstra算法。
- 初始化: 将起始节点A的距离设置为0,其他节点的距离设置为无穷大,表示未知。将所有节点标记为未访问。
A: 0 (visited)
B: ∞ (unvisited)
C: ∞ (unvisited)
D: ∞ (unvisited)
F: ∞ (unvisited)
-
选择下一个节点: 选择距离起始节点最近的节点A。
-
更新距离: 更新与节点A相邻的节点的距离。此时节点B、D与节点A相邻,更新它们的距离。
A: 0 (visited)
B: 4 (unvisited)
C: ∞ (unvisited)
D: 3 (unvisited)
F: ∞ (unvisited)
-
标记节点: 标记节点A为已访问。
-
重复步骤2-4: 选择距离起始节点最近的未访问节点D。
-
更新距离: 更新与节点D相邻的节点的距离。
A: 0 (visited)
B: 4 (unvisited)
C: 6 (unvisited)
D: 3 (visited)
F: ∞ (unvisited)
-
标记节点: 标记节点D为已访问。
-
重复步骤2-4: 选择距离起始节点最近的未访问节点B。
-
更新距离: 更新与节点B相邻的节点的距离。
A: 0 (visited)
B: 4 (visited)
C: 6 (unvisited)
D: 3 (visited)
F: 9 (unvisited)
-
标记节点: 标记节点B为已访问。
-
重复步骤2-4: 选择距离起始节点最近的未访问节点C。
-
更新距离: 更新与节点C相邻的节点的距离。
A: 0 (visited)
B: 4 (visited)
C: 6 (visited)
D: 3 (visited)
F: 9 (unvisited)
-
标记节点: 标记节点C为已访问。
-
重复步骤2-4: 选择距离起始节点最近的未访问节点F。
-
更新距离: 更新与节点F相邻的节点的距离。
A: 0 (visited)
B: 4 (visited)
C: 6 (visited)
D: 3 (visited)
F: 9 (visited)
- 标记节点: 标记节点F为已访问。
算法结束,最短路径的结果如下:
- 从A到B的最短距离为4
- 从A到C的最短距离为6
- 从A到D的最短距离为3
- 从A到F的最短距离为9
模板例题:求从顶点A出发的最短路径
import heapq
import math
# 定义图的邻接字典
graph = {
"A": {"B": 5, "C": 1},
"B": {"A": 5, "C": 2, "D": 1},
"C": {"A": 1, "B": 2, "D": 4, "E": 8},
"D": {"B": 1, "C": 4, "E": 3, "F": 6},
"E": {"C": 8, "D": 3},
"F": {"D": 6}
}
# 初始化距离字典
def init_distance(graph, s):
distance = {s: 0}
for vertex in graph:
if vertex != s:
distance[vertex] = math.inf # 初始时,将除起始顶点外的距离都设为无穷大
return distance
# Dijkstra算法实现
def dijkstra(graph, s):
pqueue = [] # 优先队列,用于存储待处理的顶点 (distance, vertex)
heapq.heappush(pqueue, (0, s)) # 将起始顶点放入队列,距离为0
seen = set() # 用于存储已经处理过的顶点
parent = {s: None} # 记录每个顶点的父节点
distance = init_distance(graph, s) # 初始化距离字典
while len(pqueue) > 0:
pair = heapq.heappop(pqueue)
dist = pair[0] # 当前顶点到起始顶点的距离
vertex = pair[1] # 当前顶点
seen.add(vertex)
nodes = graph[vertex].keys()
for w in nodes:
if w not in seen:
# 如果通过当前顶点可以获得更短的路径,则更新距离和父节点信息
if dist + graph[vertex][w] < distance[w]:
heapq.heappush(pqueue, (dist + graph[vertex][w], w))
parent[w] = vertex
distance[w] = dist + graph[vertex][w]
return parent, distance
# 调用Dijkstra算法计算从顶点"A"出发的最短路径信息
parent, distance = dijkstra(graph, "A")
# 打印结果
print("父节点:", parent)
print("最短路径:", distance)
想要了解更多可以参考一下博客:
https://www.cnblogs.com/goldsunshine/p/12978305.html
https://yxudong.github.io/Dijkstra-%E6%9C%80%E7%9F%AD%E8%B7%AF%E5%BE%84%E7%AE%97%E6%B3%95-Python-%E5%AE%9E%E7%8E%B0/
题单:Dijkstra 算法
右边数字为难度分。
2642. 设计可以求最短路径的图类 1811
1514. 概率最大的路径 1846
1631. 最小体力消耗路径 1948 做法不止一种
1368. 使网格图至少有一条有效路径的最小代价 2069 也可以 0-1 BFS
1786. 从第一个节点出发到最后一个节点的受限路径数 2079
1976. 到达目的地的方案数 2095
2662. 前往目标的最小代价 2154
2045. 到达目的地的第二短时间 2202 也可以 BFS
882. 细分图中的可到达节点 2328
2203. 得到要求路径的最小带权子图 2364
2577. 在网格图中访问一个格子的最少时间 2382
2699. 修改图中的边权 2874

浙公网安备 33010602011771号