目錄

戴克斯特拉演算法

封面圖片由 ChatGPT 生成。

前言

戴克斯特拉演算法(Dijkstra’s Algorithm)是探討最短路徑的一種演算法,最早是用於尋找兩點間的最短路徑,後拓展到由固定一點尋找與其他點的最短路徑,稱為該點的「最短路徑樹」。

戴克斯特拉演算法範例,2025年7月2日擷取自維基百科,作者為 Subh83。

運作原理

https://raw.githubusercontent.com/Josh-test-lab/website-assets-repository/refs/heads/main/posts/Dijkstra's%20Algorithm/example_0.jpg
六個地點間的關係圖。
如上圖,假設現在有六個地點,依序為 $A$ 、 $B$ 、 $C$ 、 $D$ 、 $E$ 、 $F$ 。現在以 $A$ 點為起點, $F$ 點為終點,欲尋找 $A$ 點到 $F$ 點的最短路徑。

首先,計算各路徑的距離,如下圖所示。

https://raw.githubusercontent.com/Josh-test-lab/website-assets-repository/refs/heads/main/posts/Dijkstra's%20Algorithm/example_1.jpg
六個地點間個路徑的距離。

提醒
兩點間的路徑距離也可以視作該路徑的權重,戴克斯特拉演算法與其大部分變種都無法處理權重為負的問題。

為了找到從 $A$ 點出發的最短路徑,以下建立表格用於記錄路徑尋找過程中的前一個地點與距離。為了比較最短路徑,將距離的預設值寫為無窮大($\infty$),以用於比較大小。

地點標記距離前一個地點
A$\infty$
B$\infty$
C$\infty$
D$\infty$
E$\infty$
F$\infty$

因為出發點為 $A$ ,自己與自己的距離為 0 ,因此將表格中 $A$ 的距離記為 0 。

地點標記距離前一個地點
A0
B$\infty$
C$\infty$
D$\infty$
E$\infty$
F$\infty$

接下來,檢查所有未標記的地點,找到未標記的地點中距離最短的那一個並進行標記,表示為最佳路徑。

地點標記距離前一個地點
A0
B$\infty$
C$\infty$
D$\infty$
E$\infty$
F$\infty$

由前項計算完 $A$ 地點後,將與 $A$ 地點相鄰的所有地點的前一個地點記為 $A$ ,同時更新其距離。由先前的圖可以看到, $A$ 地點與 $B$ 和 $C$ 相鄰,且 4 小於預設距離 $\infty$ ,將其更新為 4 。

地點標記距離前一個地點
A0
B4A
C4A
D$\infty$
E$\infty$
F$\infty$

接下來,再次重新尋找未標記的地點中距離最短的那一個並進行標記,表示為最佳路徑。可以看到目前 $B$ 和 $C$ 都擁有最短距離,這裡先標記 $B$ 。

地點標記距離前一個地點
A0
B4A
C4A
D$\infty$
E$\infty$
F$\infty$

現在,更新 $B$ 地點相鄰的幾個地點 $D$ 和 $E$ 。從 $D$ 開始計算,可以發現 $A$ 經過 $B$ 抵達 $D$ 的距離為 $4 + 7 = 11$ , 11 比表格上 $D$ 的距離欄之值 $\infty$ 還小,將 11 更新取代 $\infty$ 並將前一個地點記為 $B$ ;而從 $A$ 經過 $B$ 再到 $E$ 的距離是 $9$ ,也小於 $\infty$,這裡也做相同的動作。

地點標記距離前一個地點
A0
B4A
C4A
D11B
E9B
F$\infty$

接下來,繼續尋找未標記的地點中距離最短的那一個並進行標記,找到 $C$ 地點為距離最小,並嘗試更新其鄰近地點 $E$ 和 $F$ 。

地點標記距離前一個地點
A0
B4A
C4A
D11B
E9B
F$\infty$

$E$ 和 $F$ 的距離為 12 和 20。我們可以發現到 F 的距離為 $C$ 點距離 $4$ 加上 $C 到 $F$ 的路徑長 16 ,得到 $ $20 < \infty$ ,更新 $F$ 的資訊;而 E 點的距離為 12 , 比表格上的距離欄位的 9 還大,不是最佳路徑,故不更新。

地點標記距離前一個地點
A0
B4A
C4A
D11B
E9B
F20C

接下來重複標記未被標記的最短路徑,並更新其相鄰的地點,直到所有地點都被標記。最終可以得到如下表格。

地點標記距離前一個地點
A0
B4A
C4A
D11B
E9B
F18E

從以上表格,我們不僅可以知道最短路徑距離為 18 ,還能從終點 $F$ 反推最佳路徑到起點 $A$ 。由上表,可以知道最佳路徑為 $$ A \Rightarrow B \Rightarrow E \Rightarrow F $$

演算法

根據以上範例,可以大致總結戴克斯特拉演算法步驟如下:

  1. 從未標記的地點選擇距離起點的最短路徑。
  2. 標記該路徑。
  3. 計算經該路徑到其鄰近地點的距離。
  4. 若距離總長度小於目前所記錄的距離,更新該地點的距離,並記錄前一個地點;若距離總長度大於目前所記錄的距離,直接進行下一步。
  5. 回到第 1 步並重複執行,直到所有地點都被標記。

結語

初次見到這個演算法,讓我覺得大受震撼,原來我們所熟悉的最短路徑可以使用簡單的幾個步驟就可以算出來了。如果沒有見識到這一種演算法,或許我會很暴力的,將每一個點之間的距離都算出來吧?

參考資料