『算法設計_僞代碼』貪心算法_最短路徑Dijkstra算法

Dijkstra算法其實是一個貪婪算法(Greedy algorithm)。由於該算法老是試圖優先訪問每一步循環中距離起始點最近的下一個結點。Dijkstra算法的過程以下圖所示。算法

Dijkstra Animation

初始化

  1. 給定圖中的一個結點s做爲起始點。
  2. 給定一個數組dist[]存儲圖中全部結點到s的距離。將dist[s]初始化爲0。對於圖中的其餘結點v,初始化dist[v]爲無窮大。初始化爲無窮大的意義在於咱們假設其他全部結點在當前狀況下還沒有與s聯通。隨着算法的執行,dist[v]會保存圖中從sv的最短路徑的距離。
  3. 給定一個minimum Heap,記爲Q。堆頂爲當前狀況下距離s最近的結點及相應的距離。將(s, 0)放入堆中。
  4. 給定一個Set,記爲S,保存全部已經訪問過的結點。Set初始爲空。基於Dijkstra算法的性質,咱們老是以最短的路徑遍歷每個結點,所以對於任一結點,一旦咱們已經訪問過,就表明着咱們已經獲得了從s到達這一結點的最短路徑。

計算最短路徑

  1. Q不爲空的狀況下,取出堆頂的元素(v, [dist[v]) —— 也就是當前距離s最近的結點v,及其距離dist[v]
  2. 若是vS中,則表明咱們已經訪問過v的最短路徑。那麼跳過當前v,重複步驟1。
  3. 不然,將v放在S中。
  4. 對於每個與v相鄰的結點t
    • 若是dist[v] + weight(v, t) < dist[t],則更新dist[t] = dist[v] + weight(v, t)。同時將(t, dist[t])放進Q中。
    • 不然,不作任何處理。

當算法結束後,dist[]中保存圖中每個除s以外的結點到s的最短路徑的權重值(或長度)。若是從sv不存在聯通的路徑,則dist[v] = ∞數組

證實算法正確性

假設對於每一個已經訪問過的結點vdist[v]存儲從起始點sv的最短路徑。spa

當算法初始化時,dist[]中只包含dist[s] = 0,其正確性顯而易見。code

對於其他n-1個結點,假設u已經被訪問且v還沒有被訪問,同時uv之間存在一條邊u -> v,其權重爲weight(u,v),那麼必定有dist[v] = dist[u] + weight(u, v)。不然的話,假設存在另外一條更短的路徑dist[t]知足dist[t] + weight(t, v),則根據上述算法,t必定先於u被訪問,則與咱們當前的假設產生了矛盾。該論斷對於餘下的全部結點都成立。blog

所以Dijkstra算法必定能給出從出發點到其他全部結點(在能夠到達的狀況下)的最短路徑。 it

複雜度分析

設圖中總計有E條邊,N個結點。io

時間複雜度:O(ElogE)。由於所使用的最小堆最大可達O(E)大小,同時咱們從其中將每一個元素取出來一次。循環

空間複雜度:O(N+E)。其中O(N)爲存儲dist所用空間。O(E)爲存儲圖的鄰接鏈表及最小堆所用空間。遍歷

 

相關文章
相關標籤/搜索