最短路徑之貝爾曼-福特算法

基本概念算法

圖:ide

最短路徑之貝爾曼-福特算法

有頂點和邊組成。又分爲3d

有向圖:code

最短路徑之貝爾曼-福特算法

在這裏只能從A到B,不能從B到A。blog

無向圖:隊列

最短路徑之貝爾曼-福特算法

能從A到B,也能從B到A,也能夠用下圖表示:it

最短路徑之貝爾曼-福特算法

還有就是給邊加上權重,變成加權圖:class

最短路徑之貝爾曼-福特算法

權重表明了兩個頂點鏈接的程度,它能夠是時間、距離、路費等等,根據實際狀況而定。搜索

最短路徑:循環

最短路徑之貝爾曼-福特算法

如上圖,從A到D,有三種路徑:ABD、AD、ACD。

考慮到邊的權重(好比路費),三條線路中最短路徑不是兩點直連的AD(10),而是ABD(2+3=5)。

負環路:

雖然從現實場景中,人們很難想象邊的權重是負數——沒據說過走高速從A到B,不用交高速費,還倒找錢的。

可是從理論上來講,仍是要考慮負權邊的存在,這就致使一個問題:負環路的存在致使沒法找出最短路徑。

看下圖:

最短路徑之貝爾曼-福特算法

從A到A,花費的是0,這是最短路徑了,可是由於有了負權邊的存在,會形成:

A-B-C-A,權重爲2+2-5=-1,也就是說A繞了一圈,變成-1,比0小,最短路徑是ABCA了。

這還沒完,再繞一圈,-1+2+2-5=-2,A變成了-2,照此循環下去,A到A的權重會愈來愈小。

這就是負環路,永遠找不到最短路徑。

固然,有負權邊不表明必定有負環路,以下圖:

最短路徑之貝爾曼-福特算法

這就沒有造成負環路,A到C的最短路徑就是ABC=3

廣度搜索優先:

簡單地說,就是從根節點開始,搜索完其子節點後,再搜索子節點的子節點,直至找到目標節點或全部節點都被遍歷一遍。

最短路徑之貝爾曼-福特算法

如上圖,將根節點A的子節點BCD放入隊列,取出B,再將B的子節點EF放入隊列,接着取出C,再將C的子節點G放入隊列,按照隊列先進先出的特性,遍歷全部節點。

深度搜索優先:

從根節點開始,搜索完一條分支後,再搜索另外一分支。

最短路徑之貝爾曼-福特算法

如上圖,取根節點A壓入棧。

取出A,獲取A的子節點BCD,壓入棧。

取出B,獲取B的子節點EF,壓入棧。

取出F,並沒有子節點,且不是目標節點,拋出。E同理。

取出C,獲取C的子節點G,壓入棧。

取出G,同F。

取出D,獲取D的子節點H,壓入棧。

取出H,同F。

鬆弛操做:

最短路徑之貝爾曼-福特算法

如上圖,算出A到D的最短路徑。

一開始咱們只知道A到A的路徑是0,到BCD的路徑未知,就設爲∞。

計算A-D路徑爲0+10=10 <∞,故將D由∞改成10。這就是一次鬆弛操做。

貝爾曼-福特算法

簡單地說,就是對圖中全部訂單、全部邊都進行鬆弛操做,直到找到最短路徑。因此其時間複雜度應該是O(頂點數*邊數)。

僞代碼應該是:

for(int i=0;i<頂點數-1;i++){
 for(int j=0;j<邊數;j++){
  鬆弛操做;
 }
}

但在實際狀況中,在小於「頂點數-1」次的遍歷中,已經求出了最短路徑,因此在內部循環結束後,校驗一下有沒有進行鬆弛操做,若是沒有,則說明已求出最短路徑,直接跳出便可。

僞代碼:

for(int i=0;i<頂點數-1;i++){
 是否進行了鬆弛操做=false;
 for(int j=0;j<邊數;j++){
  if(終點權重>起點權重+邊權重){
   鬆弛操做:終點權重=起點權重+邊權重;終點的起點設爲起點名稱;
   是否進行了鬆弛操做=true;
  }
 }
 if(沒有進行鬆弛操做){
  break;
 }
}

再結合以前談到的負環路,在執行完最多頂點數-1次循環後,理應獲得最短路徑,若是咱們額外再遍歷一次全部的邊,看看有沒有進行鬆弛操做。若是有,說明存在負環路。

添加僞代碼:

是否存在負環路=false;
for(int j=0;j<邊數;j++){
 if(終點權重>起點權重+邊權重){
  是否存在負環路=true;
  break;  
 }
}

操做步驟:

最短路徑之貝爾曼-福特算法

如上圖,共有5個頂點:ABCDE。

16條邊(無向圖,每條線表明兩個邊):AB、AC、AD、BA、BC、BE、CA、CB、CD、CE、DA、DC、DE、EB、EC、ED

以A爲起點,計算到其餘頂點的最短路徑。

初始狀態下,A的權重應爲0,其餘節點皆爲∞。

一、處理AB,B的權重改成1。此時A=0,B=1,其他爲∞。B的起點爲A。

二、處理AC,C的權重改成7。此時A=0,B=1,C=7。C的起點爲A。

三、處理AD,D的權重改成6。此時A=0,B=1,C=7,D=6。D的起點爲A。

四、處理BA,BA=1+1=2>0,無須進行鬆弛操做。

五、處理BC,BC=1+1=2<7,C的權重改成2,此時A=0,B=1,C=2,D=6。C的起點改成B。

六、接着繼續處理,本次對全部邊的循環,得出以下結果:

A到各點最低消耗:A=0,B=1,C=2,D=6,E=4

各點的起點:B<--A,C<--B,D<--A,E<--C。

七、接着開啓下一輪對全部邊的循環,在這次循環中,沒有進行鬆弛操做,故跳出循環。

八、判斷沒有負環路,至此得出最終結果。

相關文章
相關標籤/搜索