短小精悍的多源最短路径算法—Floyd算法
前言
在圖論中,在尋路最短路徑中除了Dijkstra算法以外,還有Floyd算法也是非常經典,然而兩種算法還是有區別的,Floyd主要計算多源最短路徑。
在單源正權值最短路徑,我們會用Dijkstra算法來求最短路徑,并且算法的思想很簡單——貪心算法:每次確定最短路徑的一個點然后維護(更新)這個點周圍點的距離加入預選隊列,等待下一次的拋出確定。但是雖然思想很簡單,實現起來是非常復雜的,我們需要鄰接矩陣(表)儲存長度,需要優先隊列(或者每次都比較)維護一個預選點的集合。還要用一個boolean數組標記是否已經確定、還要---------
總之,Dijkstra算法的思想上是很容易接受的,但是實現上其實是非常麻煩的。但是單源最短路徑沒有更好的辦法。復雜度也為O(n2)
而在n節點多源最短路徑中,如果從Dijkstra算法的角度上,只需要將Dijkstra封裝,然后執行n次Dijkstra算法即可,復雜度為O(n3)。但是這樣感覺很臃腫,代碼量巨大,占用很多空間內存。有沒有啥方法能夠稍微變變口味呢?
答案是有的,這就是易寫但稍需要理解的Floyd算法。一個求多元最短路徑算法。
算法介紹
先看看百度百科的定義吧:
Floyd算法又稱為插點法,是一種利用動態規劃的思想尋找給定的加權圖中多源點之間最短路徑的算法,與Dijkstra算法類似。該算法名稱以創始人之一、1978年圖靈獎獲得者、斯坦福大學計算機科學系教授羅伯特·弗洛伊德命名。
簡單的來說,算法的主要思想是動態規劃(dp),而求最短路徑需要不斷松弛(熟悉spfa算法的可能熟悉松弛)。
而算法的具體思想為:
其中第三步的狀態轉移方程為:
- dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j])
其中dp[x][y]的意思可以理解為x到y的最短路徑。所以dp[i][k]的意思可以理解為i到k的最短路徑dp[k][j]的意思可以理解為k到j的最短路徑.
咱們圖解一個案例:
默認的最短長度初始為鄰接矩陣初始狀態
- 加入第一個節點1,大家可以發現,由于1的加入,使得本來不連通的2,3點對和2,4點對變得聯通,并且加入1后距離為當前最小。(可以很直觀加入5之后2,4,更短但是還沒加入)。為了更好的描述其實此時的直接聯通點多了兩條。(2,3)和(2,4).我們在dp中不管這個結果是通過前面那些步驟來的,但是在這個狀態,這兩點的最短距離就算它!
- 同時你可以發現加入1其中也使得3,1,4這樣聯通,但是 3,1,4聯通的話距離為9遠遠大于本來的(3,4)為2,所以不進行更新。
- 咱們繼續加入第二個節點。在加入的初始態為:
- 進行遍歷插入看看是否更新節點
實際上這個時候圖中的連線就比較多了。當然這些連線都是代表當前的最短路徑。 這也和我們的需求貼合,我們最終要的是所有節點的最短路徑。每個節點最終都應該有6條指向不同節點的邊! 表示鄰接矩陣的最終結果。
至于算法的模擬兩部核心已經告訴大家了,大家可以自行模擬剩下的。
程序實現
而對于程序而言,這個插入的過程相當簡單。核心代碼只有四行!
代碼如下
結果為:
可以自行計算,圖和上篇的Dijkstra是一致的,大家可以自行比對,結果一致,說明咱么的結果成功的。
當然,在你學習的過程中,可以在每加入一個節點插入完成后,打印鄰接矩陣的結果,看看前兩部和筆者的是否相同(有助于理解),如果相同,則說明正確!
你可能還會有疑惑,那咱么就用一個局部性來演示一下,看其中AB最短距離變化情況祝你理解:
好啦,Floyd算法就介紹到這里,如果對你有幫助,請動動小手點個贊吧!蟹蟹。
希望和各位共同進步!歡迎關注筆者公眾號:bigsai!
總結
以上是生活随笔為你收集整理的短小精悍的多源最短路径算法—Floyd算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构与算法—单源最短路径dijkst
- 下一篇: springboot整合spring C