图——图的Floyd法最短路径实现

1,Dijkstra 算法一次性求得起始顶点到所有其它顶点的最短路径,如果想要求解任意两个顶点之间的最短路径,可将图中顶点作为起始顶点执行 n 次 Dijkstra 算法就可以了;

  

2,可能解决方案:

      

       1,算法执行结束后,i 到 j 最短路径值存储于 dist[i][j] 中。最短路径前驱结点存储于 path[N][N] 中;

       2,这种方法比较土;

      

3,问题的提法:

       1,已知一个各边权值均大于 0 的带权有向图,对每一对顶点 vi != vj,求出 vi 与 vj 之间的最短路径值以及最短路径上的顶点;

         

4,Floyd 算法核心:

       1,定义一个 n 阶方阵序列:

             

          其中:

           

       2,怀疑当前两个顶点间路径不是最短路径,因此 Floyd 算法尝试通过其他顶点中转、直到找到一个中转点的中转路径最短;

         

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,路径矩阵记录了最短路径上的各个顶点;

转载于:https://www.cnblogs.com/dishengAndziyu/p/10926671.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值