Dijkstra 算法用来计算边权均非负的单源最短路径算法。
Dijkstra 算法简介
Dijkstra 算法是一种用于在加权图中找到单源最短路径的贪心算法,适用于边权非负的图。其核心思想是通过逐步扩展已知最短路径的顶点集合,最终得到从源点到所有其他顶点的最短路径。
算法步骤
-
初始化
- 创建一个距离数组
dist[]
,dist[v]
表示源点到顶点v
的当前最短距离。初始时,dist[源点] = 0
,其余顶点为无穷大(∞
)。 - 创建一个优先队列(最小堆)或未处理顶点集合,用于存储待处理的顶点。
- 创建一个距离数组
-
选择未处理顶点中距离最小的顶点
- 从优先队列中取出距离最小的顶点
u
,标记为已处理。
- 从优先队列中取出距离最小的顶点
-
松弛操作(Relaxation)
- 遍历
u
的所有邻接顶点v
,检查是否通过u
可以缩短到v
的距离:- 若
dist[u] + weight(u, v) < dist[v]
,则更新dist[v]
为dist[u] + weight(u, v)
。 - 将
v
加入优先队列(若未处理)。
- 若
- 遍历
-
重复步骤 2-3
- 直到所有顶点均被处理或优先队列为空。
伪代码实现
def dijkstra(graph, source):
dist = {v: float('infinity') for v in graph}
dist[source] = 0
priority_queue = [(0, source)]
visited = set()
while priority_queue:
current_dist, u = heapq.heappop(priority_queue)
if u in visited:
continue
visited.add(u)
for v, weight in graph[u].items():
if dist[v] > current_dist + weight:
dist[v] = current_dist + weight
heapq.heappush(priority_queue, (dist[v], v))
return dist
时间复杂度
- 优先队列实现 (如二叉堆):
- 时间复杂度为 O((V + E) \\log V),其中 V 为顶点数,E 为边数。
- 数组实现 (未优化):
- 时间复杂度为 O(V\^2),适用于稠密图。
应用场景
- 路由协议(如 OSPF)。
- 地图导航中的最短路径规划。
- 网络延迟分析。
注意事项
- 仅适用于边权非负的图。若存在负权边,需使用 Bellman-Ford 算法。
- 稠密图中,使用斐波那契堆可将时间复杂度优化至 O(E + V \\log V)。
示例
假设有以下加权图(邻接表表示):
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}
}
以 'A'
为源点,运行 Dijkstra 算法后得到的 dist
结果为:
{'A': 0, 'B': 1, 'C': 3, 'D': 4}