算法之「迪傑斯特拉(Dijkstra)算法」

最短路徑

生活中,咱們經常會面臨着對路徑的最優選擇問題,多是路程最短,也多是時間最短,這個的最短路徑就相似路程最短的選擇。算法

好比在上海,乘地鐵去某個地方,上海的地鐵路線不少,從地圖上看上去就是一個網。去某個地方就會有多條路線的選擇,咱們通常就會選最短那條路線。固然,在現實生活中,還會考慮時間、換乘等因素,這裏只是舉個例子說什麼是最短路徑。數組

地鐵換乘貌似一眼就能夠看出來那條路線是最優的路線。可是在一些複雜的狀況下,人眼就很難肯定最優路線來,好比送外賣、自駕車等。人眼就很難作出最優選擇,由於路況等因素,根本無法判斷。這時就須要用算法來選擇最佳路線了。這也是這篇文章的主角:迪傑斯特拉(Dijkstra)算法。微信

迪傑斯特拉算法

迪傑斯特拉(Dijkstra,又譯戴克斯特拉)算法由荷蘭計算機科學家艾茲赫爾·迪傑斯特拉在1956年提出。使用了廣度優先搜索解決帶權有向圖的單源最短路徑問題。經過一個頂點做爲源節點而後找到該頂點到圖中全部其它節點的最短路徑,產生一個最短路徑樹。數據結構

迪傑斯特拉算法步驟

1.標記所選的初始頂點,當前距離爲 0,其他頂點設爲無窮大。
2.將具備最小當前距離的非訪問頂點設置爲當前頂點 C。
3.對於當前頂點 C 的每一個鄰居頂點 N:將當前距離 C 與鏈接 C—N 的邊緣的權重相加。 若是它小於頂點 N 的當前距離,則將其設置爲 N 的新當前距離。
4.將當前頂點 C 標記爲已訪問。
5.若是有非訪問頂點,重複步驟2,直到全部頂點均訪問。性能

迪傑斯特拉算法時間複雜度

假如咱們有 V 表示圖中的頂點個數,E 表示圖中的邊個數。優化

若是用一個鏈表或者數組來存儲全部頂點的集合,要找到最短路徑算法所需的運行時間是 O(V^{2})3d

若是用鄰接表 + 二叉堆來用做優先隊列來查找最小的頂點,那麼算法所需的時間爲 O((E+V) \log V)cdn

若是用鄰接表 + 斐波納契堆能稍微提升一些性能,讓算法運行時間達到 O(E + V \log V)blog

迪傑斯特拉算法示例

Dijkstra的算法是用來計算一個頂點(起始點)與圖中每一個其餘頂點之間的最短路徑。隊列

搜索頂點 C 和圖中其餘頂點之間的最短路徑。

首先咱們須要初始化數據,選擇頂點 C 爲初始頂點,當前距離爲 0,對於其他頂點,因爲咱們不知道最小距離,所以它開始爲無窮大。

如今與 C 相鄰的頂點爲 A、B、D,由於沒有特定的順序,咱們選擇從 A 開始。因爲 C 到 A 的權值爲 1,當前頂點的最小距離加 C—A 的權值小於默認的無窮大,因此 C—A 的最小距離爲 0+1=1。

因爲 C 到 B 的權值爲 7,當前頂點的最小距離加 C—B 的權值小於默認的無窮大,因此 C—B 的最小距離爲 0+7=7。

因爲 C 到 D 的權值爲 2,當前頂點的最小距離加 C—D 的權值小於默認的無窮大,因此 C—D 的最小距離爲 0+2=2。
此時 C—A 的最短距離爲 1;
C—B 的最短距離爲 7;
C—D 的最短距離爲 2。

選取下一個當前頂點爲 A,因爲 A 到 B 的權值爲 3,當前頂點的最小距離加 A—B 的權值小於 7,因此 C—B 的最小距離爲 1+3=4。
當前的最短路徑分別爲 C—A、C—A—B、C—D。

選取下一個當前頂點爲 D,因爲 D 到 E 的權值爲 7,當前頂點的最小距離加 D—E 的權值小於無限大,因此 C—E 的最小距離爲 2+7=9。
此時 D—B 的權值爲 5,C—B 的最小距離爲 2+5=7,大於當前的最小距離,所以不用更新 C—B 的距離。
當前的最短路徑分別爲 C—A、C—A—B、C—D、C—D—E。

選取下一個當前頂點爲 B,因爲 B 到 E 的權值爲 1,當前頂點的最小距離加 B—E 的權值小於 9,因此 C—E 的最小距離爲 4+1=5。如今更新C—E 的最短距離爲 5,全部頂點都以標記完成。

最後,最短距離分別爲 C—A=1,C—B=4,C—D=2,C—E=5。
最短路徑分別爲 C—A、C—A—B、C—D、C—A—B—E。

總結

迪傑斯特拉(Dijkstra)算法使用了廣度優先搜索解決帶權有向圖的單源最短路徑問題。經過一個頂點做爲源節點而後找到該頂點到圖中全部其它頂點的最短路徑。

用一個鏈表或者數組來作存儲的數據結構時,時間複雜度爲 O(V^{2})

但經過對存儲結構的優化,用二叉堆或者斐波納契堆來存儲時,效率上有必定的提高。

PS:
清山綠水始於塵,博學多識貴於勤。
我有酒,你有故事嗎?
微信公衆號:「清塵閒聊」。
歡迎一塊兒談天說地,聊代碼。

相關文章
相關標籤/搜索