图——图的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

时间: 2024-11-07 06:16:02

图——图的Floyd法最短路径实现的相关文章

看数据结构写代码(35) 图的邻接矩阵表示法

杂谈:最近清明小长假,好好的放松了一下.节前 和 节后 都有点 松懈.不好,不好.贵在坚持.加油. 图的邻接矩阵表示法是用 两个数组 来表示 图的数据结构.一个是顶点数组,另一个是邻接矩阵数组.邻接矩阵 里存放着 顶点的关系. 用邻接矩阵表示图,在 看 顶点之间 是否有边,或者 求顶点的度等操作时比较简单.但空间浪费巨大,在插入,删除 顶点 和边 操作时 需要 移动大量数据,造成不便.所以在插入删除比较多,节点数比较多的时候 不宜 使用这种结构. 下面上代码: 源代码网盘地址:点击打开链接 //

Floyd-Warshall求图中任意两点的最短路径

原创 除了DFS和BFS求图中最短路径的方法,算法Floyd-Warshall也可以求图中任意两点的最短路径. 从图中任取两点A.B,A到B的最短路径无非只有两种情况: 1:A直接到B这条路径即是最短路径(前提是存在此路径): 2:A先通过其他点,再由其他点到B. 我们并不知道A是否需要通过其他点间接到达B,所以只能比较,用A到B的直接路径和A先通过其他点 再间接到达B的路径长度进行比较,然后更新为较小值. 上图中若要求顶点4到顶点3的最短路径,可以比较顶点4直接到3的路径和顶点4先到1,再到3

数据结构--图--图的数组存储表示,深度优先搜索遍历和广度优先搜索遍历

图有四种存储结构:数组,邻接表,十字链表,邻接多重表.下面以数组为存储结构来实现图的深度优先搜索遍历和广度优先搜索遍历.其中广度优先搜索遍历中有用到STL中的queue,注意头文件的包含.具体代码如下: //图的数组(邻接矩阵)存储表示和深度优先遍历 const int MAX_VERTEX_NUM=20; //最大顶点数 typedef enum {DG,DN,UDG,UDN} GraphKind ;//(有向图,有向网,无向图,无向网) typedef int VRType; typedef

给他任何一套图图图u又哭了

夫人和翻译秃头一天又图图图5634564646464合格合格合格和非官方的活动符合东方给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭了给他任何一套图图图u又哭

15 图-图的遍历-基于邻接矩阵实现的BFS与DFS算法

算法分析和具体步骤解说直接写在代码注释上了 TvT 没时间了等下还要去洗衣服 就先不赘述了 有不明白的欢迎留言交流!(估计是没人看的了) 直接上代码: 1 #include<stdio.h> 2 #include<queue> 3 #include<iostream> 4 using namespace std; 5 typedef struct{ 6 int Vex[10];//顶点表 7 int Edge[10][10]; 8 int vexnum,arcnum;

UOJ #589. 图图的游戏

[题目描述]: 图图正在玩一个智力游戏:有一个n×n 的01 方格,图图要从中选出一个面积最大的矩形区域,要求这个矩形区域不能有超过k个1. 这么难的问题图图当然不会做了,他想让你帮帮他,你能解决这个问题吗? [输入描述]: 第一行包含2 个正整数n,k. 接下来n 行每行n 个整数,表示这个01方格. [输出描述]: 输出1 个整数,表示最大面积. [样例输入]: 5 4 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 1 1 1 1 1 0 0 1 0 1 [样例输出]: 12

#589. 图图的游戏

[题目描述]: 图图正在玩一个智力游戏:有一个n×n 的01 方格,图图要从中选出一个面积最大的矩形区域,要求这个矩形区域不能有超过k个1. 这么难的问题图图当然不会做了,他想让你帮帮他,你能解决这个问题吗? [输入描述]: 第一行包含2 个正整数n,k. 接下来n 行每行n 个整数,表示这个01方格. [输出描述]: 输出1 个整数,表示最大面积. [样例输入]: 5 4 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 1 1 1 1 1 0 0 1 0 1 [样例输出]: 12

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

1,最短路径的概念: 1,从有向图中某一顶点(起始顶点)到达另一顶点(终止顶点)的路径中,其权值之和最小的路径: 2,问题的提法: 1,给定一个带权有向图 G 与起始顶点 v,求从 v 到 G 中其它顶点的最短路径(每条边上都存在有意义的权值): 2,Dijkstra 算法核心是通过已知最短路径寻找未知最短路径: 3,解决思路: 1,Dijkstra 提出按路径长度的递增次序,逐步产生最短路径: 1,首先求出长度最短的一条最短路径,再参照它求出长度次短的一条最短路径,依次类推,直到从起始顶点 v

数据结构基础温故-5.图(下):最短路径

图的最重要的应用之一就是在交通运输和通信网络中寻找最短路径.例如在交通网络中经常会遇到这样的问题:两地之间是否有公路可通:在有多条公路可通的情况下,哪一条路径是最短的等等.这就是带权图中求最短路径的问题,此时路径的长度不再是路径上边的数目总和,而是路径上的边所带权值的和.带权图分为无向带权图和有向带权图,但如果从A地到B地有一条公路,A地和B地的海拔高度不同,由于上坡和下坡的车速不同,那么边<A,B>和边<B,A>上表示行驶时间的权值也不同.考虑到交通网络中的这种有向性,本篇也只讨