最短路徑演算法—Floyd(弗洛伊德)演算法
阿新 • • 發佈:2019-02-14
Floyd演算法(解決任意兩點間的最短路徑,可以正確處理有向圖或負權值的最短路徑問題):
時間複雜度O(N3),空間複雜度O(N2);
演算法思想:
Floyd演算法是一個經典的動態規劃演算法;首先我們的目標是計算頂點i到j的最短路徑,從動態規劃角度來看:
從節點i到節點j的最短路徑不外乎兩種可能:1)直接從i到j; 2) i經過若干節點再到j;所以我們可以這樣來計算i j之間的最短距離:對於每一個結點k,我們判斷Dist(i,k)+Dist(k,j)<Dist(i,j)是否成立,如果成立,則證明從i到k,再從k到j的距離比直接從i到j的距離短,所以我們更新Dist(i,j)=Dist(i,k)+Dist(k,j);
這樣,遍歷完所有的k值,則得到最終從i到j的最小距離。
Floyd演算法過程:
1、用D[i][j]記錄每兩個頂點之間的距離;
2、依次掃描每一個頂點k,以該點為基準,判斷從i經過k,再到j的距離是否小於D[i][j],若是則更新D[i][j]=D[i][k]+D[k][j];
精髓:依次掃描每一點(k),並以該點作為中介點,計算出通過k點的其他任意兩點(i,j)的最短距離,這就是floyd演算法的精髓!同時也解釋了為什麼k點這個中介點要放在最外層迴圈的原因.
typedef struct { char vertex[MAXVER]; int edges[MAXVER][MAXVER]; int n, e; }MGraph; void Floyd(MGraph g) { int D[MAXVER][MAXVER]; int path[MAXVER][MAXVER]; int n = g.n; for (int i = 0; i < n; ++i) //初始化 { for (int j = 0; j < n; ++j) { D[i][j] = g.edges[i][j]; path[i][j] = -1; } } for (int k = 0; k < n; k++) //注意:一定要理解為什麼把k放在最外層的迴圈,而不放在最內層!! { for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (D[i][j]>D[i][k] + D[k][j]) { D[i][j] = D[i][k] + D[k][j]; path[i][j] = k; } } } } }