Dijkstra算法(模板)--python实现

Dijkstra算法是一种用于解决单源最短路径问题的经典算法,其目标是找到图中从一个源节点到所有其他节点的最短路径。
下面我将详细介绍Dijkstra算法
动图展示(取自:Python实现dijkstra算法_迪杰斯特拉算法python-CSDN博客)

算法步骤:

  1. 初始化: 设置一个起始节点,将其距离设置为0,其他节点的距离设置为无穷大(或者一个极大的数),并将所有节点标记为未访问。

  2. 选择下一个节点: 从未访问的节点中选择距离起始节点最近的节点作为当前节点。

  3. 更新距离: 对于当前节点的所有邻居节点,更新其到起始节点的距离。如果通过当前节点到达邻居节点的距离比当前已知的距离更短,则更新邻居节点的距离。

  4. 标记节点: 将当前节点标记为已访问。

  5. 重复步骤2-4: 重复执行步骤2到步骤4,直到所有节点都被标记为已访问。

  6. 输出结果: 当所有节点都被标记为已访问时,算法结束,输出从起始节点到每个节点的最短距离。

示例图表:

假设我们有以下图表表示的图,其中节点之间的边代表路径,边上的数字代表路径的权重或距离。

      4         1
(A) ----- (B) ----- (C)
 | \     / |       / |
 |  \ 2 /  |  5   /  |
 |3  \(D) |     /  3 |
 |    \   |    /    \|
 |     \  |   /      (F)
 |      \ |  /        |
 |_______\| /_________|
    6      6       2
      5         7

现在我们以节点A作为起点运行Dijkstra算法。

  1. 初始化: 将起始节点A的距离设置为0,其他节点的距离设置为无穷大,表示未知。将所有节点标记为未访问。
 

A: 0 (visited) B: ∞ (unvisited) C: ∞ (unvisited) D: ∞ (unvisited) F: ∞ (unvisited)

  1. 选择下一个节点: 选择距离起始节点最近的节点A。

  2. 更新距离: 更新与节点A相邻的节点的距离。此时节点B、D与节点A相邻,更新它们的距离。

 

A: 0 (visited) B: 4 (unvisited) C: ∞ (unvisited) D: 3 (unvisited) F: ∞ (unvisited)

  1. 标记节点: 标记节点A为已访问。

  2. 重复步骤2-4: 选择距离起始节点最近的未访问节点D。

  3. 更新距离: 更新与节点D相邻的节点的距离。

 

A: 0 (visited) B: 4 (unvisited) C: 6 (unvisited) D: 3 (visited) F: ∞ (unvisited)

  1. 标记节点: 标记节点D为已访问。

  2. 重复步骤2-4: 选择距离起始节点最近的未访问节点B。

  3. 更新距离: 更新与节点B相邻的节点的距离。

 

A: 0 (visited) B: 4 (visited) C: 6 (unvisited) D: 3 (visited) F: 9 (unvisited)

  1. 标记节点: 标记节点B为已访问。

  2. 重复步骤2-4: 选择距离起始节点最近的未访问节点C。

  3. 更新距离: 更新与节点C相邻的节点的距离。

 

A: 0 (visited) B: 4 (visited) C: 6 (visited) D: 3 (visited) F: 9 (unvisited)

  1. 标记节点: 标记节点C为已访问。

  2. 重复步骤2-4: 选择距离起始节点最近的未访问节点F。

  3. 更新距离: 更新与节点F相邻的节点的距离。

 

A: 0 (visited) B: 4 (visited) C: 6 (visited) D: 3 (visited) F: 9 (visited)

  1. 标记节点: 标记节点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

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值