Dijkstra算法其實是一個貪婪算法(Greedy algorithm)。由於該算法老是試圖優先訪問每一步循環中距離起始點最近的下一個結點。Dijkstra算法的過程以下圖所示。算法
s
做爲起始點。dist[]
存儲圖中全部結點到s
的距離。將dist[s]
初始化爲0
。對於圖中的其餘結點v
,初始化dist[v]
爲無窮大。初始化爲無窮大的意義在於咱們假設其他全部結點在當前狀況下還沒有與s
聯通。隨着算法的執行,dist[v]
會保存圖中從s
到v
的最短路徑的距離。Q
。堆頂爲當前狀況下距離s
最近的結點及相應的距離。將(s, 0)
放入堆中。S
,保存全部已經訪問過的結點。Set初始爲空。基於Dijkstra算法的性質,咱們老是以最短的路徑遍歷每個結點,所以對於任一結點,一旦咱們已經訪問過,就表明着咱們已經獲得了從s
到達這一結點的最短路徑。Q
不爲空的狀況下,取出堆頂的元素(v, [dist[v])
—— 也就是當前距離s
最近的結點v
,及其距離dist[v]
。v
在S
中,則表明咱們已經訪問過v
的最短路徑。那麼跳過當前v
,重複步驟1。v
放在S
中。v
相鄰的結點t
: dist[v] + weight(v, t) < dist[t]
,則更新dist[t] = dist[v] + weight(v, t)
。同時將(t, dist[t])
放進Q
中。 當算法結束後,dist[]
中保存圖中每個除s
以外的結點到s
的最短路徑的權重值(或長度)。若是從s
到v
不存在聯通的路徑,則dist[v] = ∞
。 數組
假設對於每一個已經訪問過的結點v
,dist[v]
存儲從起始點s
到v
的最短路徑。spa
當算法初始化時,dist[]
中只包含dist[s] = 0
,其正確性顯而易見。code
對於其他n-1
個結點,假設u
已經被訪問且v
還沒有被訪問,同時u
和v
之間存在一條邊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)
爲存儲圖的鄰接鏈表及最小堆所用空間。遍歷