短小精悍的多源最短路徑算法—Floyd算法

2021-01-10 睿哥說平臺

在圖論中,在尋路最短路徑中除了

Dijkstra

算法以外,還有

Floyd

算法也是非常經典,然而兩種算法還是

有區別

的,Floyd主要計算多源最短路徑。

在單源正權值最短路徑,我們會用Dijkstra算法來求最短路徑,並且算法的思想很簡單——貪心算法:每次確定最短路徑的一個點然後維護(更新)這個點周圍點的距離加入預選隊列,等待下一次的拋出確定。但是雖然思想很簡單,

實現起來是非常複雜

的,我們需要鄰接矩陣(表)儲存長度,需要優先隊列(或者每次都比較)維護一個預選點的集合。還要用一個boolean數組標記是否已經確定、還要----

總之,

Dijkstra

算法的思想上是很容易接受的,但是實現上其實是非常麻煩的。但是單源最短路徑沒有更好的辦法。複雜度也為

O(n2)

而在n節點多源最短路徑中,如果從Dijkstra算法的角度上,只需要將Dijkstra封裝,然後執行n次Dijkstra算法即可,複雜度為

O(n3)

。但是這樣感覺很臃腫,代碼量巨大,佔用很多空間內存。有沒有啥方法能夠稍微變變口味呢?

答案是有的,這就是易寫但稍需要理解的

Floyd

算法。一個求多元最短路徑算法。

算法介紹

先看看百度百科的定義吧:

Floyd算法又稱為插點法,是一種利用動態規劃的思想尋找給定的加權圖中多源點之間最短路徑的算法,與Dijkstra算法類似。該算法名稱以創始人之一、1978年圖靈獎獲得者、史丹福大學計算機科學系教授羅伯特·弗洛伊德命名。

簡單的來說,算法的主要思想是動態規劃(dp),而求最短路徑需要

不斷鬆弛

(熟悉spfa算法的可能熟悉鬆弛)。

而算法的具體思想為:

鄰接矩陣dist儲存路徑,同時最終狀態代表點點的最短路徑。如果沒有直接相連的兩點那麼默認為一個很大的值(不要溢出)!而自己的長度為0.從第1個到第n個點依次加入圖中。每個點加入進行試探是否有路徑長度被更改,這個長度就是說兩點距離會不會因為新加入的點變得更短(a_k_b距離<a_b距離)。而上述試探具體方法為遍歷圖中每一個點(i,j雙重循環),判斷每一個點對距離是否因為加入的點而發生最小距離變化。如果發生改變,那麼兩點(i,j)距離就更改。重複上述直到最後插點試探完成。其中第三步的狀態轉移方程為:

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條指向不同節點的邊! 表示鄰接矩陣的最終結果。至於算法的模擬兩部核心已經告訴大家了,大家可以自行模擬剩下的。

程序實現

而對於程序而言,這個插入的過程相當簡單。核心代碼只有四行!代碼如下

public class floyd {static int max = 66666;// 別Intege.max 兩個相加越界為負 public static void main(String[] args) { int dist[][] = { { 0, 2, 3, 6, max, max }, { 2, 0, max,max, 4, 6 }, { 3, max, 0, 2, max, max }, { 6, max, 2, 0, 1, 3 }, { max, 4, max, 1, 0, max }, { max, 6, max, 3, max, 0 } };// 地圖 // 6個 for (int k = 0; k < 6; k++)// 加入滴k個節點 { for (int i = 0; i < 6; i++)// 鬆弛I行 { for (int j = 0; j < 6; j++)// 鬆弛i列 { dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]); } } } // 輸出 for (int i = 0; i < 6; i++) { System.out.print("節點"+(i+1)+" 的最短路徑"); for (int j = 0; j < 6; j++) { System.out.print(dist[i][j]+" "); } System.out.println(); } }}

結果為:

可以自行計算,圖和上篇的Dijkstra是一致的,大家可以自行比對,結果一致,說明咱麼的結果成功的。

當然,在你學習的過程中,可以在每加入一個節點插入完成後,列印鄰接矩陣的結果,看看前兩部和筆者的是否相同(

有助於理解

),如果相同,則說明正確!

你可能還會有疑惑,那咱麼就用一個局部性來演示一下,看其中AB最短距離變化情況祝你理解:

好啦,Floyd算法就介紹到這裡,如果對你有幫助,請動動小手點個讚吧!蟹蟹

相關焦點

  • 圖的最短路徑算法-Floyd算法-弗洛伊德算法
    Floyd算法又稱為插點法,是一種利用動態規劃的思想尋找給定的加權圖中多源點之間最短路徑的算法 在計算機科學中,Floyd-Warshall算法是一種在具有正或負邊緣權重(但沒有負周期)的加權圖中找到最短路徑的算法。算法的單個執行將找到所有頂點對之間的最短路徑的長度(加權)。
  • 單源最短路徑-Dijkstra 算法
    Dijkstra(迪傑斯特拉)算法是典型的單源最短路徑算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴展,直到擴展到終點為止。可以簡單描述為:最短路徑的子路徑也是最短路徑。2.如果考慮到邊的權值為正數,則由定理 7.2 可以得到以下結論:若π = (s , u1 , u2 , … , uk)是從s到uk的最短路徑,則從s到各頂點ui(i=1, 2, …k)的最短路徑是嚴格遞增的。
  • golang 調用 python 實戰路徑規劃之 A* 算法
    這樣做之後,一旦到達終點,便可以從終點開始,反過來順著父節點的順序找到起點,由此就構成了一條路徑。Dijkstra算法Dijkstra算法是由計算機科學家Edsger W. Dijkstra在1956年提出的。Dijkstra算法用來尋找圖形中節點之間的最短路徑。考慮這樣一種場景,在一些情況下,圖形中相鄰節點之間的移動代價並不相等。
  • 圖像處理算法有哪些_圖像處理十大經典算法
    }}二、廣度優先搜索此圖遍歷中最基本的倆種算法,BFS,DFS,入選本圖算法十大算法,自是無可爭議。因為,這倆種搜索算法,應用實為廣泛而重要。A*算法,作為啟發式算法中很重要的一種,被廣泛應用在最優路徑求解和一些策略設計的問題中。
  • 十大編程算法
    在最壞狀況下則需要Ο(n2)次比 較,但這種狀況並不常見。事實上,快速排序通常明顯比其他Ο(n log n) 算法更快,因為它的內部循環(inner loop)可以在大部分的架構 上很有效率地被實現出來。
  • 從算法上解讀自動駕駛是如何實現的?
    智能車的自動駕駛行為即是將車從起始位姿「搬運」到目標位姿,車輛的運動限制在路面上、同時其運動學及動力學模型使得其不能像空中的無人機一樣隨意調整航向角,因此,規劃的路徑除了考慮路程最短、無碰撞外還需要考慮車輛運動軌跡的可執行性。
  • 你不得不看的最重要的算法類型
    算法: 算法是解決問題的分步過程。一個好的算法應該在時間和空間上進行優化。不同類型的問題需要以最優化的方式解決不同類型的算法技術。世界上有很多類型的算法,但是本文將討論您必須知道的最重要和最基本的算法。
  • 長URL連結轉短連結算法
    開始以為短連結是按照某種算法把原始連結壓縮為短連結,再根據算法從短連結反算成原始連結的。後來嘗試了下壓縮算法(比如gzip 壓縮算法),發現對於url 這種字符串越是壓縮,長度就越長。通過對壓縮算法的一些了解,發現靠壓縮算法來實現這個功能不太靠譜。
  • 用圖形解釋10種圖形算法
    與樹不同,圖可以包含循環(第一個頂點和最後一個頂點相同的路徑)。 因此,我們必須跟蹤訪問的頂點。 在實現BFS時,我們使用隊列數據結構。圖2表示示例圖的BFS遍歷的動畫。 注意如何發現頂點(黃色)並訪問頂點(紅色)。應用領域 用於確定最短路徑和最小生成樹。
  • 翼眸科技綜述面向無人機集群路徑規劃的智能優化算法
    智能優化算法因其對優化問題的性質要求低、魯棒性高,而被廣泛應用於求解路徑規劃問題.鑑於此, 本文綜述了近些年面向無人機集群路徑規劃的智能優化算法研究, 首先介紹了無人機集群路徑規劃的基本模型, 包括規劃空間表示、優化目標函數及約束條件等, 其次闡述了基於不同智能優化算法的無人機集群路徑規劃研究現狀、詳細對比分析了不同類型算法的優勢與不足, 最後對無人機集群路徑規劃研究進行了展望.
  • 從算法層解讀,自動駕駛的「軌跡規劃」是如何實現的?
    智能車的自動駕駛行為即是將車從起始位姿「搬運」到目標位姿,車輛的運動限制在路面上、同時其運動學及動力學模型使得其不能像空中的無人機一樣隨意調整航向角,因此,規劃的路徑除了考慮路程最短、無碰撞外還需要考慮車輛運動軌跡的可執行性。三.車輛路徑規划算法 根據車輛導航系統的研究歷程, 車輛路徑規划算法可分為靜態路徑規划算法和動態路徑算法。
  • 菜鳥路徑規划算法入圍全球最高工業獎項
    其中智能路徑規划算法是新零售出現的技術基礎,創造了30分鐘—2小時內送達的新商業業態。這套算法綜合計算了顧客下單動態、需求隨機、倉內作業空間狹小、合單揀選、城市交通堵塞、末端小區登記流程、電梯等待等複雜的不確定性因素,在極短時間內給出決策,以留下足夠的線下操作時間。目前菜鳥、盒馬、餓了麼、同城零售、LAZADA等平臺均使用該算法提供服務。
  • 程式設計師必須掌握的核心算法有哪些?
    2、圖論算法圖的表示:鄰接矩陣和鄰接表遍歷算法:深度搜索和廣度搜索(必學)最短路徑算法:Floyd,Dijkstra(必學)最小生成樹算法:Prim,Kruskal(必學)實際常用算法:關鍵路徑、拓撲排序(原理與應用)二分圖匹配:配對、匈牙利算法(原理與應用)拓展:中心性算法、社區發現算法(原理與應用)圖還是比較難的,不過我覺得圖涉及到的挺多算法都是挺實用的,例如最短路徑的計算等,圖相關的,我這裡還是建議看書的,可以看
  • 自動駕駛實時路徑規划算法簡介(Local search局部搜索)
    在上一節自動駕駛實時路徑規划算法簡介(RRT 和Lattice Planner)中介紹了找到車輛要遵循的最佳幾何路徑有兩個方法:a) 通過增量採樣或離散幾何結構(即增量搜索)找到最佳的動作序列。b) 從多個最終狀態中找到最佳操作(即局部搜索)。
  • 一文帶你搞懂什麼是圖以及常見的算法實現
    >四.求出圖的最短路徑1.迪傑斯特拉算法(從單一頂點出發到其他的各個頂點的最小路徑)步驟:1.設出發頂點為v,頂點集合V{v1,v2,...vi},v到V中各頂點集合的距離集合Dis,Dis{d1,d2,...di},Dis記錄了v到圖中各個頂點的距離(到自身可以看做是0,v到vi
  • 五大常用算法:一文搞懂分治算法
    原創公眾號:bigsai文章收錄在 bigsai-algorithm前言分治算法(divide and conquer)是五大常用算法(分治算法、動態規划算法、貪心算法、回溯法、分治界限法)之一,很多人在平時學習中可能只是知道分治算法,但是可能並沒有系統的學習分治算法
  • 數據驅動歸因的幾個算法
    數據驅動歸因是一種基於機器學習的歸因模型,與基於規則的歸因模型不同,數據驅動歸因使用所有可用的路徑數據,包括路徑長度,曝光順序和廣告素材,來了解特定營銷接觸點的存在如何影響用戶轉化的可能性以更好地將功勞分配給任何接觸點。
  • 案例實踐丨最優化算法的前世今生
    那麼所謂最優化問題,就是指用最優的方式去平衡理想與現實之間的關係。以簡單的郵差送信問題為例,郵差從A出發,送信到BCD,最後回到A。郵差每天必須經過BCD,而且每個點每天只能經過一次,在這樣的約束條件下,他的目標函數是儘可能以最短的時間完成送信。這個問題非常簡單,只要把所有的路徑枚舉出來,然後取最短時間的方式即可。
  • 螞蟻、蝙蝠和青蛙,細數智能時代那些有趣的「土味」算法
    比如說……蟻群算法、蝙蝠搜索、螢火蟲算法,甚至還有蛙跳算法、人工魚群算法和…蟑螂算法???下面可以給大家介紹幾個典型的群體智能算法。蟻群算法如果仔細觀察蟻群就會發現,不論在什麼環境中,螞蟻總會組成蟻群,通過最快路徑一起搬運食物。螞蟻究竟是怎麼做到的?
  • 對話雲天勵飛CEO陳寧:算法晶片化,不等於「算法+晶片」
    正是這種晶片技術背景,使陳寧最開始的創業思路都不同於其它的AI創企。直到2018年,雲天勵飛才有了真正意義上的融資團隊,也是而後兩年,公司融資才有了起色。重技術研發的AI行業也面臨虧損居高不下的問題,引起市場憂慮,這從近期幾家AI企業披露招股書中動輒幾十億的虧損中可以略知一二。雲天勵飛如何看待這一問題?