Dijkstra 最短路徑演算法是一種用於計算從單一源點到圖中所有其他節點的最短路徑的經典演算法。這個演算法適用於加權圖,其中邊的權重必須是非負的,核心思想是每次選擇「距離起點最近」的尚未處理節點,並用它來更新鄰居的最短距離,這種策略屬於貪心演算法 (Greedy Algorithm)
假設有一個圖如下:
A --(1)--> B
A --(4)--> C
B --(2)--> C
B --(5)--> D
C --(1)--> D
Dijkstra 演算法的時間複雜度取決於使用的資料結構。若使用二元堆,時間複雜度為 $O((V + E) \log V)$,其中 $V$ 是節點數,$E$ 是邊數
import heapq
def dijkstra(graph, start):
# graph: adjacency list 格式 {u: [(v, weight), ...]}
dist = {node: float('inf') for node in graph}
dist[start] = 0
# 最小堆 (priority queue)
pq = [(0, start)]
while pq:
current_dist, u = heapq.heappop(pq)
# 如果已經不是最短路徑,跳過
if current_dist > dist[u]:
continue
for v, weight in graph[u]:
distance = current_dist + weight
if distance < dist[v]:
dist[v] = distance
heapq.heappush(pq, (distance, v))
return dist
# 測試
graph = {
0: [(1, 4), (2, 1)],
1: [(3, 1)],
2: [(1, 2), (3, 5)],
3: []
}
print(dijkstra(graph, 0))
# 輸出: {0: 0, 1: 3, 2: 1, 3: 4}
優點 | 缺點 |
---|---|
適用於大部分「非負權重」的最短路徑問題 | 無法處理負權重 |
效率高,特別適合稀疏圖 | 若要計算所有點對最短路徑需額外呼叫多次 |
與 Priority Queue 搭配能達到 $O((V+E)\log V)$ | 在稠密圖上效率不如 Floyd-Warshall |
Dijkstra 演算法是圖論中最重要的演算法之一,能高效解決單源最短路徑問題,它的貪心思想簡單卻強大,應用範圍極廣,從日常導航到金融網路分析都能見到它的身影