Dijkstra算法和Floyd算法


一、簡介

迪傑斯特拉(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

 

最短路徑不適用於負權回路,或負權環,因為每次繞行都會減小最短路徑,因此負權回路或者說負權環不存在最短路徑。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM