圖——圖的Floyd法最短路徑實現

1,Dijkstra 算法一次性求得起始頂點到全部其它頂點的最短路徑,若是想要求解任意兩個頂點之間的最短路徑,可將圖中頂點做爲起始頂點執行 n 次 Dijkstra 算法就能夠了;算法

  

2,可能解決方案:數組

      

       1,算法執行結束後,i 到 j 最短路徑值存儲於 dist[i][j] 中。最短路徑前驅結點存儲於 path[N][N] 中;spa

       2,這種方法比較土;3d

      

3,問題的提法:code

       1,已知一個各邊權值均大於 0 的帶權有向圖,對每一對頂點 vi != vj,求出 vi 與 vj 之間的最短路徑值以及最短路徑上的頂點;blog

         

4,Floyd 算法核心:遞歸

       1,定義一個 n 階方陣序列:隊列

             

          其中:get

           

       2,懷疑當前兩個頂點間路徑不是最短路徑,所以 Floyd 算法嘗試經過其餘頂點中轉、直到找到一箇中轉點的中轉路徑最短;it

         

5,n 階方陣中元素的意義:

     

       1,都是由鄰接方陣中的權值推得的;

       2,此算法是經過遞推的方式獲得兩個頂點間最短路徑的;

       3,把全部的頂點的中轉路徑都推導完了,也就獲得最小路徑了;

       4,後面方陣的推導,包含着前面方陣的信息,且每次推導都是最小,直到推導了所有頂點,獲得最終最短路徑;

      

6,Floyd 算法精髓:

 

 

7,Floyd 算法的實現:

     

       1,初始化:

              1,本質:使用鄰接矩陣初始化 A(-1);    

       2,A(0), ..., A(n-1) 矩陣推導:

    1,本質:使用中轉頂點逐步推導最短路徑;

              2,最外層是在說 A(k)矩陣的循環,循環推導完後,獲得最短路徑矩陣 A(n-1),即爲所求;

                   

 

8,如何記錄最短路徑上的各個頂點?

       1,定義輔助矩陣:

              1,int path[N][N];  // 路徑矩陣

                     1,path[i][j] 表示 i 到 j 的路徑上所通過的第 1 個頂點;

                     2,初始化:path[i][j] = -1; or paht[i][j] = j;

                            1,有直接的鏈接則設置爲 j,表示通過的第一個頂點爲終值頂點 j;

                            2,沒有鏈接的兩個頂點設置爲 -1;

                     3,修改:

1 if( (dist[i][k] + dist[k][j]) < dist[i][j]  )
2 {
3      dist[i][j] = dist[i][k] + dist[k][j];
4      path[i][j] = paht[i][k];
5 }

                            1,if 條件爲真,由 k 這個頂點中轉能夠獲得一條更短路徑,則由 i 到 j 這條路徑上所通過的第一個頂點就是由 i 到 k 這條路徑上通過的第一個頂點,由於由 k 中轉了下;

              2,路徑矩陣示例:

      1,由一個點的路徑推至其它路徑:

                     2,輔助矩陣和路徑:

 

9,Floyd 最短路徑算法實現:

 1    /* floyd 每對結點之間最短路徑算法,返回值爲最短路徑;核心爲經過中轉頂點尋找更短路徑 */
 2     SharedPointer< Array<int> > floyd(int x, int y, const E& LIMIT)  // O(n*n*n)
 3     {
 4         LinkQueue<int> ret;
 5 
 6         if( (0 <= x) && (x < vCount()) && (0 <= y) && (y < vCount()) )  //頂點編號要合理
 7         {
 8             DynamicArray< DynamicArray<E> > dist(vCount());  // 定義二維數組,N*N
 9 
10             DynamicArray< DynamicArray<int> > path(vCount());  // 最短路徑的輔助數組
11 
12             /* 定義二維數組 */
13             for(int k=0; k<vCount(); k++)
14             {
15                 dist[k].resize(vCount());
16                 path[k].resize(vCount());
17             }
18 
19             /* 初始值設置 */
20             for(int i=0; i<vCount(); i++)
21             {
22                 for(int j=0; j<vCount(); j++)
23                 {
24                     path[i][j] = -1;  // i 和 j 是沒有邊的
25 
26                     dist[i][j] = isAdjacent(i, j) ? (path[i][j]=j, getEdge(i, j)) : LIMIT;  // 鄰接了就設置,利用了逗號表達式,逗號表達式第一個參數是設置頂點,第二個是設置權值
27                 }                                                                           
28             }
29 
30             /* 推導最短路徑矩陣 */
31             for(int k=0; k<vCount(); k++)
32             {
33                 for(int i=0; i<vCount(); i++)
34                 {
35                     for(int j=0; j<vCount(); j++)
36                     {   
37                /* 推導規則,用中間頂點中轉數據,看是否有最短路徑值 */
38                         if( (dist[i][k] + dist[k][j]) < dist[i][j] )
39                         {
40                             dist[i][j] = dist[i][k] + dist[k][j];  // 若是獲得最短路徑,認爲其多是最短路徑,要更新其值
41 
42                             path[i][j] = path[i][k];  // 經過 k 頂點能夠找到最小值,則這個頂點找到了
43                          }
44                     }
45                 }
46             }
47 
48             while( (x != -1) && (x != y) )  // 推導到終止頂點爲止
49             {
50                 ret.add(x);  // 最短路徑上的各個頂點加到返回值中
51 
52                 x = path[x][y];  // 遞歸的將 path[x][y] 上通過的第一個頂點放入 x 中,而後在下一個遞推中從 x 出發再遞歸處其它頂點;
53             }
54 
55             if( x != -1 )
56             {
57                 ret.add(x);  // 將最後的一個 x 加入返回值隊列中,由於上面 x == y,終止了在返回隊列中的加入,因此這裏要加入
58             }
59         }
60         else
61         {
62             THROW_EXCEPTION(InvalidParameterException, "Index <x, y> is invalid ...");
63         }
64 
65         /* 看看目標的兩個最短值之間是否真的有最短路徑 */
66         if( ret.length() < 2 )
67         {
68             THROW_EXCEPTION(ArithmeticException, "There is no path from x to y ...");
69         }
70 
71         return toArray(ret);
72     }

 

10,小結:

       1,Floyd 算法經過遞推逐步求得全部頂點間的最短路徑;

       2,Floyd 算法的本質是經過中轉頂點尋找更短的路徑;

       3,鄰接矩陣是最短路徑推導的起始矩陣;

       4,路徑矩陣記錄了最短路徑上的各個頂點;

相關文章
相關標籤/搜索