数据结构——最短路径Floyd算法
2018-02-03 15:31
399 查看
最短路径Floyd算法
上一篇博客讲到了Dijkstra算法的原理和用C++的代码实现。Dijkstra算法可以解决任意点到其他点的最短路径问题。在Dijkstra算法中,最后一个循环是个双层循环,在最坏情况下,每个节点都可以指向其他所有节点,那么Dijkstra算法的时间复杂度就是O(n^2)了。如果想让图中每个点到其他所有点的最短路径,就需要把Dijkstra算法执行n次,那么整个算法的时间复杂度就是O(n^3)了。弗洛伊德(Floyd)算法的时间复杂度也是O(n^3),但Floyd算法更加简单。Floyd算法把dist的最终结果存在一个二维数组dist[i][j]中,dist[i][j]表示从i到j的最短路径长度
bf3b
,而路径存放在path中,path[i][j]=k表示路径为(i,...,k,j),也就是j的前一个节点是k,如果想要k的前一个节点,则是path[i][k],这样一直找下支,就可以得到i到j的完整路径。
Floyd算法是分步进行的,把dist扩展一维,形成dist[k][i][j],表示i到j的最短路径中i和j之间的节点的序号最大为k,那么最后要求的最短路径的矩阵就是dist[n-1]了。当k最小为-1时,表示i和j之间的最短路径不能有节点,而k=0时表示之间的节点序号最大不能为0。这种策略的好处就是逐渐向最短路径中添加新的节点,如果添加后路径变短了,就添加,如果没有变短就不添加。并且由于所有的最短路径在形式上都是等价的,因此可以选择拼接最短路径,这样效率更高。因为如果a->b->d比a->c->d更短,并且有e->f,那么从a->f的最短路径中,绝对不可能是a->c->d->e->f,而仅可能是a->b->d->e->f。这种思路更加清晰。
下面是用C++实现的Floyd算法
#include "stdafx.h" #include <iostream> using namespace std; const int MAX = 1e5; /** * 求当前节点的第一个邻接节点 */ int FirstAdjVex(int **weights,int size,int cv) { if(cv < 0 || cv >= size) { return -1; } for (int i = 0;i < size;i++) { if (weights[cv][i]) { return i; } } return -1; } /** * 计算当前节点cv基于av的下一个邻接节点 */ int NextAdjVex(int **weights,int size,int cv,int av) { if (cv < 0 || cv >= size || av < 0 || av >= size - 1) { return -1; } for (int i = av + 1;i < size;i++) { if (weights[cv][i]) { return i; } } return -1; } void Floyd(int **weights,int size,int **dist,int **paths) { //初始化dist for (int i = 0;i < size;i++) { for (int j = 0;j < size;j++) { if(i==j) { dist[i][j] = 0; }else if(weights[i][j] == 0)//i和j不相等且j不是i的邻接节点 { dist[i][j] = MAX; } else { dist[i][j] = weights[i][j]; } if(i!=j&&dist[i][j]<MAX)//如果i和j不相等并且j是i的邻接节点 { paths[i][j] = i; } else { paths[i][j] = -1; } } } for (int k = 0;k < size;k++)//k的0到n-1 { for (int i = 0;i < size;i++) { for (int j = 0;j < size;j++) { if(dist[i][k]+dist[k][j]<dist[i][j]) { dist[i][j] = dist[i][k] + dist[k][j]; paths[i][j] = paths[k][j]; } } } } } int main() { //构造有向图 int size = 3; int **weights = new int*[size]; for (int i = 0;i < size;i++) { weights[i] = new int[size]; for (int j = 0;j < size;j++) { weights[i][j] = 0; } } weights[0][1] = 4; weights[0][2] = 11; weights[1][0] = 6; weights[1][2] = 2; weights[2][0] = 1; int **paths = new int*[size];//存放路径 int **dist = new int*[size];//存入v0到每个节点的最短路径的长度 for (int i = 0;i < size;i++) { paths[i] = new int[size]; dist[i] = new int[size]; } Floyd(weights, size, dist, paths); for (int i = 0;i < size;i++) { for (int j = 0;j < size;j++) { cout << dist[i][j] << " "; } cout << " "; for (int j = 0;j < size;j++) { cout << paths[i][j] << " "; } cout << endl; } cout << "--------------------------------" << endl; int index; for (int i = 0;i < size;i++) { for (int j = 0;j < size;j++) { if (i != j) { cout << i << " ---> " << j << " dist: " << dist[i][j] << endl; for (index = j;;) { if(index == i) { cout << i; break; } if (paths[i][index] < 0) { cout << "no way!"; break; } cout << index << " <- "; index = paths[i][index]; } cout << endl; } } } system("pause"); return 0; }
下面是执行结果
横线上面是打印的dist矩阵和path矩阵,下面的是每个节点到其他所有节点的最短路径的长度以及路径
相关文章推荐
- 数据结构与算法15:单源最短路径弗洛伊德Floyd算法
- 数据结构20————图的最短路径Dijkstra算法&Floyd算法
- 数据结构之(图最短路径之)Dijkstra(迪杰斯特拉)算法
- 数据结构与算法12:单源最短路径Dijkstra算法
- 数据结构与算法——无权最短路径算法的C++实现
- 图结构练习——最短路径(floyd算法(弗洛伊德))
- 温习 数据结构之求最短路径 Dijstra
- 数据结构基础温故-5.图(下):最短路径
- 数据结构实验之图论七:驴友计划(最短路径之Dijkstra算法+Bellman-Ford算法)
- 数据结构之---C语言实现最短路径之Dijkstra(迪杰斯特拉)算法
- 数据结构与算法--拓补排序及无环加权有向图的最短路径
- 数据结构课程设计:两顶点之间最短路径
- 数据结构图之四(最短路径--迪杰斯特拉算法)
- 43. 数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法
- 数据结构-图-最短路径(2)弗洛伊德算法构造
- 【数据结构与算法】 有向图的最短路径实现
- 数据结构:单源最短路径--Dijkstra算法
- 数据结构:图——图的遍历、最小生成树、最短路径算法
- 数据结构——单源最短路径Dijkstra算法
- 算法——数据结构图的最短路径实现JAVA代码