Dijkstra算法是由荷兰计算机科学家艾兹格·迪科斯彻(Edsger W. Dijkstra)于1959年提出的,是一种解决带权图中单源最短路径问题的经典算法。该算法主要用于寻找图中从给定的源点(起点)到所有其他顶点的最短路径。在有向图或无向图中,只要边的权重非负,Dijkstra算法都能准确地找出从源点到每个顶点的最短路径。对于存在负权边的图,Dijkstra算法不再适用,此时应使用其他算法,如Bellman-Ford算法或Johnson's algorithm。
主要特点:
-
贪心策略:Dijkstra算法采用贪心策略,每次选择当前已知距离源点最近且未确定最短路径的顶点进行扩展。这种策略保证了在每一步选择中,总是朝着全局最优方向推进。
-
优先队列优化:虽然基础版本的Dijkstra算法可以用普通队列实现,但为了提高效率,通常会使用优先队列(如二叉堆)来存储未访问节点,这样每次都能直接获取距离源点最近的未访问节点。
-
松弛操作:在算法过程中,通过“松弛”操作不断更新顶点间的最短路径估计值。每当发现一条更短的路径到达某个顶点时,就更新该顶点的最短路径估计值及其前驱节点信息。
基本步骤:
-
初始化:
- 将源点的距离设为0,其余顶点的距离设为无穷大(或一个非常大的值)。
- 使用一个数据结构(如优先队列)按距离排序未访问节点,初始时源点排在首位。
- 初始化一个数据结构(如数组或映射)来存储每个顶点的前驱节点,用于回溯构建最短路径。
-
循环处理:
- 从优先队列中取出距离最小的未访问节点(称为当前节点)。
- 对当前节点的每个未访问邻居节点:
- 计算从源点经由当前节点到该邻居节点的路径长度。
- 如果这个路径长度比已知的邻居节点距离源点的路径长度更短,则:
- 更新邻居节点到源点的最短距离。
- 将当前节点设置为邻居节点的前驱节点(用于路径重建)。
- 标记当前节点为已访问。
-
结束条件:当优先队列为空或者已访问了目标节点(若指定的话)时,算法结束。
应用实例:
Dijkstra算法广泛应用于各种需要计算最短路径的场景,例如:
- 路径规划(如地图导航系统中的路线计算)。
- 网络路由(如互联网协议中的路由选择)。
- 社交网络中的朋友关系链分析。
- 电路设计中的布线优化。
以下是Dijkstra算法的Python实现示例(以邻接列表表示带权图,并使用内置的heapq
模块实现优先队列):
Python
1import heapq
2
3def dijkstra(graph, source):
4 distances = {node: float('inf') for node in graph}
5 distances[source] = 0
6 priority_queue = [(0, source)] # (distance, node)
7
8 while priority_queue:
9 current_distance, current_node = heapq.heappop(priority_queue)
10
11 if current_distance > distances[current_node]:
12 continue # Skip nodes that were already updated by a shorter path.
13
14 for neighbor, weight in graph[current_node].items():
15 distance_through_current = current_distance + weight
16 if distance_through_current < distances[neighbor]:
17 distances[neighbor] = distance_through_current
18 heapq.heappush(priority_queue, (distance_through_current, neighbor))
19
20 return distances
21
22# 示例
23graph = {
24 'A': {'B': 1, 'C': 4},
25 'B': {'A': 1, 'D': 2, 'E': 5},
26 'C': {'A': 4, 'F': 8},
27 'D': {'B': 2, 'E': 1},
28 'E': {'B': 5, 'D': 1, 'F': 3},
29 'F': {'C': 8, 'E': 3}
30}
31
32shortest_distances = dijkstra(graph, 'A')
33print("Shortest distances from A:", shortest_distances)
实现了Dijkstra算法的核心逻辑,使用字典distances
存储每个顶点到源点的最短距离,优先队列priority_queue
则按距离排序待访问节点。遍历结束后,返回一个字典,其中包含了从源点到每个顶点的最短距离。
收起