【最短路徑Floyd算法詳解推導過程】看完這篇陡叠,你還能不懂Floyd算法?還不會肢执?

簡介

 Floyd-Warshall算法(Floyd-Warshall algorithm)枉阵,是一種利用動態(tài)規(guī)劃的思想尋找給定的加權圖中多源點之間最短路徑的算法,與Dijkstra算法類似预茄。該算法名稱以創(chuàng)始人之一兴溜、1978年圖靈獎獲得者、斯坦福大學計算機科學系教授羅伯特·弗洛伊德命名耻陕。

簡單的說就是解決任意兩點間的最短路徑的一種算法拙徽,可以正確處理有向圖或負權的最短路徑問題,同時也被用于計算有向圖的傳遞閉包诗宣。Floyd-Warshall算法的時間復雜度為O(N3)膘怕,空間復雜度為O(N2)。

解決最短路徑問題有幾個出名的算法:

  • 1.dijkstra算法,最經(jīng)典的單源最短路徑算法

  • 2.bellman-ford算法,允許負權邊的單源最短路徑算法

  • 3.spfa,其實是bellman-ford+隊列優(yōu)化,其實和bfs的關系更密一點

  • 4.floyd算法,經(jīng)典的多源最短路徑算法

今天先說說Floyd

Floyd算法詳解

描述

a)如圖:存在【0,1,2,3】 4個點召庞,兩點之間的距離就是邊上的數(shù)字岛心,如果兩點之間来破,沒有邊相連,則無法到達忘古,為無窮大徘禁。
b)要讓任意兩點(例如從頂點a點到頂點b)之間的路程變短,只能引入第三個點(頂點k)髓堪,并通過這個頂點k中轉即a->k->b送朱,才可能縮短原來從頂點a點到頂點b的路程。那么這個中轉的頂點k是0~n中的哪個點呢干旁?


image.png

算法過程

準備

1)如圖 0->1距離為5骤菠,0->2不可達,距離為∞疤孕,0->3距離為7……依次可將圖轉化為鄰接矩陣(主對角線商乎,也就是自身到自身,我們規(guī)定距離為0祭阀,不可達為無窮大)鹉戚,如圖矩陣 用于存放任意一對頂點之間的最短路徑權值。


image.png

2)再創(chuàng)建一個二維數(shù)組Path路徑數(shù)組专控,用于存放任意一對頂點之間的最短路徑抹凳。每個單元格的內容表示從i點到j點途經(jīng)的頂點。(初始還未開始查找伦腐,默認-1)


image.png
image.png

開始查找

1)列舉所有的路徑(自己到自己不算)

image.png

即為:
0 -> 1 , 0 -> 2 , 0 -> 3 ,
1 -> 0 , 1 -> 2 , 1 -> 3 ,
2 -> 0 , 1 -> 1 , 1 -> 3
轉化成二元數(shù)組即為:
{0赢底,1},{0柏蘑,2}幸冻,{0,3}咳焚,{1洽损,0},{1革半,2}碑定,{1,3}又官,{2延刘,0},{2六敬,1}碘赖,{2,3},{3崖疤,0},{3典勇,1}劫哼,{3,2}

2)選擇編號為0的點為中間點

{0割笙,1}权烧,{0,2}伤溉,{0般码,3},{1乱顾,0}板祝,{1,2}走净,{1券时,3},{2伏伯,0}橘洞,{2,1}说搅,{2炸枣,3},{3弄唧,0}适肠,{3,1}候引,{3迂猴,2}
從上面中二元組集合的第一個元素開始,循環(huán)執(zhí)行以下過程:

1. 用i背伴,j兩個變量分別指向二元組里的兩個元素沸毁,比如{0,1}這個二元組傻寂,i指向0息尺;j指向1
2. 判斷 (A[ i ][ 0 ]+A[ 0 ][ j ] ) < A[ i ][ j ] (即判斷 i -> j,i點到j點的距離是否小于從0點中轉的距離)疾掰,如果false搂誉,則判斷下一組二元數(shù)組。
3. 如果表達式為真静檬,更新A[ i ] [ j ]的值為A[ i ] [ 0 ] + A[ 0 ] [ j ]炭懊,Path[ i ] [ j ]的值為點0(即設置i到j要經(jīng)過0點中轉)

{0并级,1}按照此過程執(zhí)行之后,

image.png

0->0 + 0->1的距離不小于0->1 侮腹,下一組{0嘲碧,2},{0父阻,3}愈涩, {1,0}加矛,{2履婉,0},{3斟览,0}也同理毁腿。

{1,2}按照此過程執(zhí)行苛茂,A[1,0] 無窮大狸棍, A[0,2]也是無窮大,而A[1,4] = 4味悄,則1點到2點肯定不會從0點中轉草戈。

A[1][0]無窮大同理下一組{1,2}侍瑟, {1唐片,3}也同理

{2涨颜,1}按照此過程執(zhí)行费韭,A[2][0] = 3 ,A[0][1]=5 ,A[2][1] = 3那么 A[2][0]+ ,A[0][1] > A[2][1]
…………
依次類推庭瑰,遍歷二元組集合星持,沒有0點適合做中轉的

3)選擇編號為1的點為中間點

4)選擇編號為2的點為中間點

依次類推,遍歷二元組集合{0弹灭,1}督暂,{0,2}穷吮,{0逻翁,3},{1捡鱼,0}八回,{1,2},{1缠诅,3}溶浴,{2,0}管引,{2士败,1},{2汉匙,3},{3生蚁,0}噩翠,{3,1}邦投,{3伤锚,2}
,當遍歷{3志衣,0}時屯援,A[3][2] = 1 ,A[2][0]=3 ,A[3][0] = 不可達念脯,那么 2點適合做從3點到0點之間的中轉點狞洋。
設置距離矩陣A[3][0] = 1+3 =4 ,Path矩陣Path[3][0] = 2點绿店,表示從3到0在2點中轉吉懊,距離最近。


image.png

如圖表示(紅色單元格)假勿,從3到0借嗽,最近距離為4,在2點中轉 转培。

依次類推恶导,遍歷完二元組集合


image.png

5)選擇編號為3的點為中間點,最終結果

依次類推浸须,遍歷二元組集合惨寿,直到所有的頂點都做過一次中間點為止。


image.png

6)根據(jù)最終結果删窒,就可以知道任意2點的最短距離和路徑

比如1點到2點怎么走缤沦?根據(jù)路徑Path矩陣,Path[1][2] = 3,表示從點3中轉易稠,即 1-> 3 ->2


image.png

6)如果中轉點不止1個呢缸废?

有時候不只通過一個點,而是經(jīng)過兩個點或者更多點中轉會更短,即a->k1->k2b->或者a->k1->k2…->k->i…->b企量。
比如頂點1到頂點0测萎,我們看數(shù)組Path
Path[1][0] = 3,說明頂點3是中轉點届巩,那么再從3到0
Path[3][0] = 2硅瞧,說明從3到0,頂點2是中轉點恕汇,然后在從2到0
Path[2][0] = -1腕唧,說明頂點2到頂點0沒有途徑頂點,也就是說瘾英,可以由頂點2直接到頂點0枣接,即它們有邊連接。

最終缺谴,最短路徑為1->3->2->0但惶,距離為 A[1][0] = 6 。
顯然湿蛔,這是一個逐層遞進膀曾,遞歸的過程。

算法實現(xiàn)

基本定義

    //    表示無窮大 即不可達
    public static int MAX = Integer.MAX_VALUE;
    //    距離矩陣
    public int[][] dist;
    //    路徑Path矩陣
    public int[][] path;

核心算法

//        核心算法
       for(int k = 0 ; k < size ; k++){
           for(int i = 0;i < size;i++){
               for(int j = 0 ;j < size;j++){
//                判斷如果 ik距離可達且 kj距離可達 且 i和j的距離是否大于 i-> k 與 k->j的距離和
                    if( dist[i][k] != MAX &&  dist[k][j] != MAX  &&  dist[i][j] > (dist[i][k] + dist[k][j]) ){
                        path[i][j]= k;
                        dist[i][j]= dist[i][k] + dist[k][j];
                    }
               }
           }
       }

運行結果

image.png

源碼下載

Floyd算法java實現(xiàn)-下載

Floyd算法java實現(xiàn)

看完這篇文章如果你還不會Floyd阳啥,請留言評論添谊。


image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市察迟,隨后出現(xiàn)的幾起案子碉钠,更是在濱河造成了極大的恐慌,老刑警劉巖卷拘,帶你破解...
    沈念sama閱讀 212,185評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喊废,死亡現(xiàn)場離奇詭異,居然都是意外死亡栗弟,警方通過查閱死者的電腦和手機污筷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,445評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乍赫,“玉大人瓣蛀,你說我怎么就攤上這事±壮В” “怎么了惋增?”我有些...
    開封第一講書人閱讀 157,684評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長改鲫。 經(jīng)常有香客問我诈皿,道長林束,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,564評論 1 284
  • 正文 為了忘掉前任稽亏,我火速辦了婚禮壶冒,結果婚禮上,老公的妹妹穿的比我還像新娘截歉。我一直安慰自己胖腾,他們只是感情好,可當我...
    茶點故事閱讀 65,681評論 6 386
  • 文/花漫 我一把揭開白布瘪松。 她就那樣靜靜地躺著咸作,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宵睦。 梳的紋絲不亂的頭發(fā)上记罚,一...
    開封第一講書人閱讀 49,874評論 1 290
  • 那天,我揣著相機與錄音状飞,去河邊找鬼毫胜。 笑死书斜,一個胖子當著我的面吹牛诬辈,可吹牛的內容都是我干的。 我是一名探鬼主播荐吉,決...
    沈念sama閱讀 39,025評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼焙糟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了样屠?” 一聲冷哼從身側響起穿撮,我...
    開封第一講書人閱讀 37,761評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎痪欲,沒想到半個月后悦穿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,217評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡业踢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,545評論 2 327
  • 正文 我和宋清朗相戀三年栗柒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片知举。...
    茶點故事閱讀 38,694評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡瞬沦,死狀恐怖,靈堂內的尸體忽然破棺而出雇锡,到底是詐尸還是另有隱情逛钻,我是刑警寧澤,帶...
    沈念sama閱讀 34,351評論 4 332
  • 正文 年R本政府宣布锰提,位于F島的核電站曙痘,受9級特大地震影響芳悲,放射性物質發(fā)生泄漏。R本人自食惡果不足惜屡江,卻給世界環(huán)境...
    茶點故事閱讀 39,988評論 3 315
  • 文/蒙蒙 一芭概、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惩嘉,春花似錦罢洲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,778評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至耸峭,卻和暖如春桩蓉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背劳闹。 一陣腳步聲響...
    開封第一講書人閱讀 32,007評論 1 266
  • 我被黑心中介騙來泰國打工院究, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人本涕。 一個月前我還...
    沈念sama閱讀 46,427評論 2 360
  • 正文 我出身青樓业汰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親菩颖。 傳聞我的和親對象是個殘疾皇子样漆,可洞房花燭夜當晚...
    茶點故事閱讀 43,580評論 2 349