演算法 最短路徑之弗洛伊德(Floyd)演算法

2022-08-09 03:00:18 字數 2724 閱讀 4040

為了能講明白弗洛伊德(floyd)演算法的主要思想,我們先來看最簡單的案例。圖7-7-12的左圖是乙個簡單的3個頂點的連通網圖。

我們先定義兩個二維陣列d[3][3]和p[3][3], d代表頂點與頂點的最短路徑權值和的矩陣。p代表對應頂點的最短路徑的前驅矩陣。在未分析任何頂點之前,我們將d命名為d(-1),其實它就是初始圖的鄰接矩陣。將p命名為p(-1), 初始化為圖中的矩陣。

首先我們來分析,所有的頂點經過v0後到達另一頂點的最短路徑。因為只有3個頂點,因此需要檢視v1->v0->v2,得到

d(-1)[1][0] + d(-1)[0][2] = 3。d(-1)[1][2]表示的是v1->v2的權值為5,我們發現d(-1)[1][2] > d(-1)[1][0] + d(-1)[0][2] ,通俗話來說就是

v1->v0->v2 比v1->v2距離還要近。所以我們就讓 d(-1)[1][2] = d(-1)[1][0] + d(-1)[0][2] = 3, 同樣地d(-1)[2][1] = 3, 於是就有了d(0)矩陣。因為有變化,所以p矩陣對應的p(-1)[1][2]和p(-1)[2][1]也修改為當前中轉的頂點v0的下標0, 於是就有了p(0)。也就是說

接下來,也就是在d(0)和p(0)的基礎上繼續處理所有頂點經過v1和v2後到達另一頂點的最短路徑,得到d(1)和p(1)、d(2)和p(2)完成所有頂點到所有頂點的最短路徑計算工作。

首先我們針對圖7-7-13的左網圖準備兩個矩陣d(-1)和p(-1),d(-1)就是網圖的鄰接矩陣,p(-1)初設為p[i][j]=j 這樣的矩陣。主要用來儲存路徑。

**如下(改編自《大話資料結構》):注意因為是要求所有頂點到所有頂點的最短路徑,因為使用二維陣列。

#includeusing

namespace

std;

#define maxedge 20

#define maxvex 20

#define infinity 65535typedef

struct

mgraph;

typedef

intpatharc[maxvex][maxvex];

typedef

intshortpathtable[maxvex][maxvex];

/*構建圖

*/void createmgraph(mgraph *g)

for (i = 0; i < g->numvertexes; i++)/*

初始化圖

*/ }

g->arc[0][1] = 1

; g->arc[0][2] = 5

; g->arc[1][2] = 3

; g->arc[1][3] = 7

; g->arc[1][4] = 5

; g->arc[2][4] = 1

; g->arc[2][5] = 7

; g->arc[3][4] = 2

; g->arc[3][6] = 3

; g->arc[4][5] = 3

; g->arc[4][6] = 6

; g->arc[4][7] = 9

; g->arc[5][7] = 5

; g->arc[6][7] = 2

; g->arc[6][8] = 7

; g->arc[7][8] = 4

;

for(i = 0; i < g->numvertexes; i++)

}}/*

floyd演算法,求網圖g中各頂點v到其餘頂點w的最短路徑p[v][w]及帶權長度d[v][w]。

*/void

shortestpath_floyd(mgraph mg, patharc p, shortpathtable d)

}for (k = 0; k < mg.numvertexes; k++)}}

}}int main(void

) cout

<< "

->

"<< w <

}cout

<

}return0;

}

輸出為:

程式中的演算法**非常簡潔,即用了乙個三層迴圈,k代表的是中轉結點的下標,v代表起始結點,w代表結束終點。k = 0 ~ 8,表示針對每個頂點作為中轉結點得到的計算結果,最終當k = 8時,兩矩陣資料如圖7-7-16所示。

從上圖我們可以看到第v2行的數值與dijkstra演算法求得的d陣列的數值完全一樣,都是, 而且這裡是所有頂點到所有頂點的最短路徑權值和都可以計算得出。那麼如何由p這個路徑陣列得出具體的最短路徑呢?以v2到v8為例,p[2][8] = 4,說明要經過頂點v4, 將4替換2,p[4][8] = 3, 說明經過v3, ......., 最終推導出最短路徑為:v2->v4->v3->v6->v7->v8。

floyd演算法使用了三層迴圈,故時間複雜度也為o(n^3),與dijkstra演算法一致,不過floyd演算法**簡潔,雖簡潔但也不一定好懂,還是需要多加揣摩才能領會。另外,雖然我們使用的例子都是無向圖的,但它們對於有向圖依然有效,只不過在建立圖的時候,有向圖的鄰接矩陣不是對稱的而已。

最短路徑之弗洛伊德

floyd演算法是大二到大三期間集訓時候才算真正接觸的,或許只有前一段時間dp的積累現在才算是真正理解 這個演算法需要充分理解dp的滾動陣列思想才能算是真正的掌握 floyd演算法又稱為插點法 演算法的目標是要求圖中所有兩個點的最短距離,就用dis i j 來表示 但是dis i j 是不夠設定為狀...

MPI之弗洛伊德最短路徑演算法

include include include for debugging include const int infinity 1000000 void read matrix int local mat,int n,int my rank,int p,mpi comm comm void pri...

弗洛伊德演算法求最短路徑

include includeusing namespace std 鄰接矩陣的型別定義 define max 10000000 define max vertex num 20 typedef struct mgraph 構造有向網的鄰接矩陣 void createdn am mgraph g,i...