一、簡介
迪傑斯特拉(Dijkstra)算法和弗洛伊德(Flyod)算法均是用於求解有向圖或無向圖從一點到另外一個點最短路徑。
二、Dijkstra
迪傑斯特拉算法也是圖論中的明星算法,主要是其采用的動態規划思想,使其在數據結構、算法、離散數學乃至運籌學中都扮演重要的角色。以下圖為例:
以A為起點,首先走一步,共有三條邊,分別如下:
AB(12),AF(16),AG(14)其中最短的是節點B,將AB(12)放入輔助向量。
接着,各節點均繼續向下走,此時可以找出4條邊。
ABC(22),ABF(19),AF(16),AG(14),同樣找出最小值放入向量中。{AB(12),AG(14)}
此后步驟完全相同
ABC(22),ABF(19),AF(16),AGF(23),AGE(22),選中AF(16)。
同樣,接下來的步驟有:ABC(22),AFC(22),AFE(18),AGE(22),選中AFE(18);
ABC(22),AFC(22),AFEC(23),AFED(22),這種情況隨便選取一個最小值,以ABC(22)為例;
ABCD(25),AFED(22)選中后者,至此,已經完全找到A和所有節點之間的最短路徑及最短路徑的長度。
最短路徑向量為{AB(12),AG(14),AF(16),AFE(18),ABC(22),AFED(22)}
三、Floyd
弗洛伊德是另外一種求最短路徑的方式,與迪傑斯特拉算法不同,弗洛伊德偏重於多源最短路徑的求解,即能迪傑斯特拉能夠求一個節點到其余所有節點的最短路徑,但是弗洛伊德能夠求出任意兩個節點的最短路徑,當然迪傑斯特拉重復N次也能達到目標。兩種方式的時間復雜度均為O(n^3),但弗洛伊德形式上會更簡易一些。
以下面的有向有權圖為例:
老版visio不知道為啥這么糊?
首先寫出圖的鄰接矩陣Adj
A | B | C | D | |
A | 0 | 4 | 2 | 6 |
B | 5 | 0 | ∞ | 12 |
C | ∞ | ∞ | 0 | 3 |
D | 7 | 1 | ∞ | 0 |
若想縮短兩點間的距離,僅有一種方式,那就是通過第三節點繞行,如果我們假設僅能通過A點繞行,那么僅需判斷是否現有的距離Adj[i][j]小於Adj[i][1]+Adj[1][j]的距離,如果有更短的選擇,那么進行更新就好了。首先第一行和第一列肯定不會更新,然后對角線也不必更新。【其實通過觀察可以知道,第三行也不會進更新,因為C根本無法繞到A】
0 | 4 | 2 | 6 |
5 | 0 | 7 | 11 |
∞ | ∞ | 0 | 3 |
7 | 1 | 9 | 0 |
接下來,開放繞行節點2,那么就相當於可以經過節點1和2進行繞行。更新條件是Adj[i][j]>Adj[i][2]+Adj[2][j],除去第2行,第2列和對角線不需要進行判斷。可以到D到C通過B-A會比僅通過A更短。
0 | 4 | 2 | 6 |
5 | 0 | 7 | 11 |
∞ | ∞ | 0 | 3 |
6 | 1 | 8 | 0 |
然后開放節點3.
0 | 4 | 2 | 5 |
5 | 0 | 7 | 10 |
∞ | ∞ | 0 | 3 |
6 | 1 | 8 | 0 |
最后開放節點4.
0 | 4 | 2 | 5 |
5 | 0 | 7 | 10 |
9 | 4 | 0 | 3 |
6 | 1 | 8 | 0 |
最短路徑不適用於負權回路,或負權環,因為每次繞行都會減小最短路徑,因此負權回路或者說負權環不存在最短路徑。