[Python]Dijkstra 演算法實作

更新 發佈閱讀 10 分鐘

Dijkstra 演算法實作

Dijkstra 是用來找到從一個起點到其他所有點的最短路徑的演算法,適合靜態地圖。

實作步驟

  1. 定義地圖:使用圖(Graph)表示地圖。
  2. 初始化距離:起點距離設為 0,其餘點設為無限大。
  3. 遍歷節點:逐步找出距離最短的節點,更新相鄰節點的距離。
  4. 結束條件:所有節點被訪問完成。

程式碼

import heapq  # 引入 heapq 模組,實現最小堆優先隊列

def dijkstra(graph, start):
# 初始化最短距離字典,將所有節點的最短距離設為無窮大
distances = {node: float('inf') for node in graph}
distances[start] = 0 # 起點到自己的距離為 0

# 儲存已訪問的節點集合,避免重複處理節點
visited = set()

# 初始化優先隊列,將起點節點及其距離 0 加入隊列
priority_queue = [(0, start)] # 優先隊列中的元素是 (距離, 節點)

while priority_queue:
# 從優先隊列中取出距離最小的節點
current_distance, current_node = heapq.heappop(priority_queue)

# 如果當前節點已經訪問過,跳過該節點
if current_node in visited:
continue

# 將當前節點標記為已訪問
visited.add(current_node)

# 遍歷當前節點的所有鄰居
for neighbor, weight in graph[current_node].items():
# 計算從起點到鄰居的距離
distance = current_distance + weight
# 如果新計算出的距離比已知距離更短,則更新最短距離
if distance < distances[neighbor]:
distances[neighbor] = distance
# 將鄰居節點和其新的距離加入優先隊列
heapq.heappush(priority_queue, (distance, neighbor))

# 返回從起點到所有節點的最短距離
return distances

# 測試圖:節點間的連接與對應的邊的權重
graph = {
'A': {'B': 1, 'C': 4}, # 節點 A 與 B 的距離為 1,A 與 C 的距離為 4
'B': {'A': 1, 'C': 2, 'D': 5}, # 節點 B 與 A 的距離為 1,B 與 C 的距離為 2,B 與 D 的距離為 5
'C': {'A': 4, 'B': 2, 'D': 1}, # 節點 C 與 A 的距離為 4,C 與 B 的距離為 2,C 與 D 的距離為 1
'D': {'B': 5, 'C': 1} # 節點 D 與 B 的距離為 5,D 與 C 的距離為 1
}

start_node = 'A' # 設定起點為節點 A
# 呼叫 dijkstra 函數,計算從節點 A 出發的最短距離
shortest_distances = dijkstra(graph, start_node)

# 輸出結果,顯示從節點 A 到其他節點的最短距離
print("Shortest distances from node A:", shortest_distances)

測試輸出

對於這個測試例子,演算法會計算並返回從節點 A 到其他節點的最短距離,輸出結果應該如下:

Shortest distances from node A: {'A': 0, 'B': 1, 'C': 3, 'D': 4}

這表示:

  • 從 A 到 A 的距離是 0。
  • 從 A 到 B 的最短距離是 1。
  • 從 A 到 C 的最短距離是 3。
  • 從 A 到 D 的最短距離是 4。


程式碼詳細解說


1. 引入 heapq 模組

import heapq

heapq 是 Python 的標準庫,用於實現最小堆(min-heap)。在 Dijkstra 演算法中,我們使用最小堆來高效地選擇當前距離最小的節點。

2. 定義 dijkstra 函數

def dijkstra(graph, start):

這個函數接受兩個參數:

  • graph:一個字典表示圖,節點作為鍵,與該節點相連的鄰居節點及其邊的權重作為值。
  • start:起點節點,演算法從這個節點開始計算最短距離。

3. 初始化最短距離字典

distances = {node: float('inf') for node in graph}
distances[start] = 0 # 起點距離為 0
  • 我們使用 distances 字典來存儲每個節點到起點的最短距離。初始時,所有節點的距離設定為無窮大(float('inf')),表示尚未被訪問過。
  • 然後,將起點的距離設置為 0,因為起點到自身的距離是 0。

4. 初始化已訪問節點集合

visited = set()

visited 集合用來存儲已經訪問過的節點。這樣可以避免再次訪問同一節點。

5. 初始化優先隊列

priority_queue = [(0, start)]  # (距離, 節點)

priority_queue 是一個優先隊列,用來存儲尚未訪問的節點,並且根據距離進行排序(最小堆)。初始時,我們將起點節點和其距離(0)加入隊列。

6. 主迴圈

while priority_queue:
current_distance, current_node = heapq.heappop(priority_queue)

這是 Dijkstra 演算法的核心部分:

  • 當優先隊列不為空時,不斷循環。
  • 我們使用 heapq.heappop(priority_queue) 來取出當前距離最小的節點。這會返回一個二元組 (distance, node),即節點的距離和節點本身。

7. 如果節點已訪問過,跳過

if current_node in visited:
continue

如果當前節點已經在 visited 集合中,說明它已經被處理過,這時就跳過它,繼續處理下一個節點。

8. 標記節點為已訪問

visited.add(current_node)

將當前節點標記為已訪問,這樣就不會再次處理它。

9. 更新鄰居節點的距離

for neighbor, weight in graph[current_node].items():
distance = current_distance + weight
if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(priority_queue, (distance, neighbor))

對於當前節點的每一個鄰居:

  • graph[current_node].items() 返回當前節點的所有鄰居及其邊的權重。
  • 計算從起點到鄰居的距離:distance = current_distance + weight
  • 如果計算出的距離比鄰居當前的距離短,則更新鄰居的最短距離,並將這個鄰居節點及其新的距離加入優先隊列。

10. 返回最短距離字典

return distances

當所有節點都處理完後,返回 distances 字典,其中包含了從起點到每個節點的最短距離。

11. 測試地圖與呼叫函數

# 節點間的連接與距離
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}
}

start_node = 'A'
shortest_distances = dijkstra(graph, start_node)
print("Shortest distances from node A:", shortest_distances)

這段程式碼定義了一個圖 graph,其中每個節點的鄰居和對應的邊權重以字典的形式給出。然後,呼叫 dijkstra 函數來計算從節點 A 出發的最短距離,並將結果打印出來。


留言
avatar-img
螃蟹_crab的沙龍
168會員
322內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。 興趣是攝影,踏青,探索未知領域。 人生就是不斷的挑戰及自我認清,希望老了躺在床上不會後悔自己什麼都沒做。
你可能也想看
Thumbnail
定義 圖Graph: 由節點和邊所組成的一個網狀資料結構。 圖的表達方式Graph representation: 常見的有相鄰串列adjacency list或相鄰矩陣adjacency matrix。 本文以adjacenct list作為示範。
Thumbnail
定義 圖Graph: 由節點和邊所組成的一個網狀資料結構。 圖的表達方式Graph representation: 常見的有相鄰串列adjacency list或相鄰矩陣adjacency matrix。 本文以adjacenct list作為示範。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這篇文章,會帶著大家複習以前學過的格子點DP框架, 並且以移動路徑Unique Path的概念與應用為核心, 貫穿一些相關聯的題目,透過框架複現來幫助讀者理解這個演算法框架。 格子點DP框架 依循題目的定義和規則,找出格子點移動的共同模式。 以本篇文章的例題為例,每一步可以選擇往右走一個
Thumbnail
這篇文章,會帶著大家複習以前學過的格子點DP框架, 並且以移動路徑Unique Path的概念與應用為核心, 貫穿一些相關聯的題目,透過框架複現來幫助讀者理解這個演算法框架。 格子點DP框架 依循題目的定義和規則,找出格子點移動的共同模式。 以本篇文章的例題為例,每一步可以選擇往右走一個
Thumbnail
5 月將於臺北表演藝術中心映演的「2026 北藝嚴選」《海妲・蓋柏樂》,由臺灣劇團「晃晃跨幅町」製作,本文將以從舞台符號、聲音與表演調度切入,討論海妲・蓋柏樂在父權社會結構下的困境,並結合榮格心理學與馮.法蘭茲對「阿尼姆斯」與「永恆少年」原型的分析,理解女人何以走向精神性的操控、毀滅與死亡。
Thumbnail
5 月將於臺北表演藝術中心映演的「2026 北藝嚴選」《海妲・蓋柏樂》,由臺灣劇團「晃晃跨幅町」製作,本文將以從舞台符號、聲音與表演調度切入,討論海妲・蓋柏樂在父權社會結構下的困境,並結合榮格心理學與馮.法蘭茲對「阿尼姆斯」與「永恆少年」原型的分析,理解女人何以走向精神性的操控、毀滅與死亡。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
定義 圖Graph: 由節點和邊所組成的一個網狀資料結構。 圖的表達方式Graph representation: 常見的有相鄰串列adjacency list或相鄰矩陣adjacency matrix。 本文以adjacenct list作為示範。 節點Vertex: 節點
Thumbnail
定義 圖Graph: 由節點和邊所組成的一個網狀資料結構。 圖的表達方式Graph representation: 常見的有相鄰串列adjacency list或相鄰矩陣adjacency matrix。 本文以adjacenct list作為示範。 節點Vertex: 節點
Thumbnail
本篇文章討論了在給定二元矩陣中,如何使用Dijkstra算法找出從左上角到右下角的最安全路徑的安全分數。包括定義曼哈頓距離、最安全路徑的算法以及時間複雜度和空間複雜度分析。最終推薦Dijkstra algorithm和priority queue的使用。文章提供了參考文獻LeetCode的連結。
Thumbnail
本篇文章討論了在給定二元矩陣中,如何使用Dijkstra算法找出從左上角到右下角的最安全路徑的安全分數。包括定義曼哈頓距離、最安全路徑的算法以及時間複雜度和空間複雜度分析。最終推薦Dijkstra algorithm和priority queue的使用。文章提供了參考文獻LeetCode的連結。
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
Minimum Path Sum 給定一個矩陣,每個格子點代表經過的對應成本。 每回合可以往右移動一格或往下移動一格。 請問從起點左上角 走到 終點右下角的最小路徑成本總和是多少?
Thumbnail
Minimum Path Sum 給定一個矩陣,每個格子點代表經過的對應成本。 每回合可以往右移動一格或往下移動一格。 請問從起點左上角 走到 終點右下角的最小路徑成本總和是多少?
Thumbnail
這題算是路徑計數類的DP衍伸題(路徑數、方法數、組合數...等等這種枚舉類的題目,第一時間切入除了想到DFS+回溯法之外,也可以留意DP動態規劃解題的可能性) 題目會給我們一個指定長度為arrLen的陣列,起點從index=0開始出發,每次移動可以往左移一格,往右移一格,或是留在原地不
Thumbnail
這題算是路徑計數類的DP衍伸題(路徑數、方法數、組合數...等等這種枚舉類的題目,第一時間切入除了想到DFS+回溯法之外,也可以留意DP動態規劃解題的可能性) 題目會給我們一個指定長度為arrLen的陣列,起點從index=0開始出發,每次移動可以往左移一格,往右移一格,或是留在原地不
Thumbnail
這篇文章,會帶著大家複習以前學過的 格子點DP框架, 並且以最小成本的下降路徑的應用題與概念為核心, 貫穿一些相關聯的題目,透過框架複現來幫助讀者理解這個演算法框架。 最小成本下降路徑的形式 每個格子點的值代表經過的成本。 要求從最上面那排往下方走,落到最下一排的最小成本的下降路徑。
Thumbnail
這篇文章,會帶著大家複習以前學過的 格子點DP框架, 並且以最小成本的下降路徑的應用題與概念為核心, 貫穿一些相關聯的題目,透過框架複現來幫助讀者理解這個演算法框架。 最小成本下降路徑的形式 每個格子點的值代表經過的成本。 要求從最上面那排往下方走,落到最下一排的最小成本的下降路徑。
Thumbnail
Min-Heap 最小堆是一種特殊的樹狀資料結構, 其中每個節點的值都小於或等於其子節點的值。這意味著最小值總是位於根節點。 Min-Heap 常用於實作優先權佇列 (Priority Queue)、Dijkstra 演算法、 排序以及尋找中位數等應用。
Thumbnail
Min-Heap 最小堆是一種特殊的樹狀資料結構, 其中每個節點的值都小於或等於其子節點的值。這意味著最小值總是位於根節點。 Min-Heap 常用於實作優先權佇列 (Priority Queue)、Dijkstra 演算法、 排序以及尋找中位數等應用。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News