最短路径算法(Dijkstra、Floyd)总结
来源:互联网 发布:js给div input赋值 编辑:程序博客网 时间:2024/06/05 01:02
引言
最短路径算法是图算法中比较重要的组成部分,在《算法导论》中有比较详细的阐述和证明。很长时间没在看过图算法的内容,在接触到增强学习后,复习了下A*算法,故对最短路径算法进行一下简单的总结,A*算法将会另外开一篇文章。Dijkstra和Floyd算法是最为经典的两个针对无向图进行最短路径求取的算法,本文先对这两个算法进行回顾和总结。
Dijkstra算法
Dijkstra算法在解决最短路径算法时有一定的局限性,要求图中不能存在负边权重(具体的证明可参考《算法导论》)。个人看来Dijkstra算法应该属于贪心算法的部分,但某些参考书籍把它归入到了动态规划的范围。当然我们不会对这个问题深究,看自己证明好理解吧。Dijkstra是从源点出发,一次求取到其余所有点的最短路径。这也称为单源最短路径。
如上图,现在我们要求从源点
(1). 将
(2). 选取与
(3). 由于
(4). 以此类推,选择
最后
const int MAXINT = INT_MAX; //图中不直接连接的点的权重定义const int MAXNUM = 6; //图中的节点数目int dst[MAXNUM]; //存放源点到其它点的距离int prev[MAXNUM]; //存放路径int G[MAXNUM][MAXNUM]; //图的邻接矩阵void Dijstra(int v0){ bool used[MAXNUM]; // 判断图中节点时候已经被加入最后的结果中,初始为false int node_num = MAXNUM; for(int i = 1; i<=n; i++) { dst[i] = G[v0][i]; //从邻接矩阵中获取距离信息 used[i] = false; if( MAXINT == dst[i] ) prev[i] = -1; else prev[i] = v0; // 设置源点直接连接的点的前驱为源点 } dst[v0] = 0; // 源点到源点的距离设置为0 used[v0] = true; //标记源点已经被加入最后的结果中 for(int i = 2; i <= n; i++){ int mindst = MAXINT; int u = v0; for(int j = 1; j <= n; j++) // 选取目前距离矩阵中与源点最短距离的点 { if( (!used[j]) && dst[j] < mindst){ u = j; mindst = dst[j]; } used[u] = true; //将该点加入到最后结果中 for(int j = 1; j <= n; ++j) { if( (!used[j]) && G[u][j] < MAXINT) { if(dst[u]+G[u][j] < dst[j]) { dst[j] = dst[u]+G[u][j]; // 更新距离 pre[j] = u; // 设置前驱 } } } } }}
Floyd算法
Dijkstra算法是解决单源最短路径算法,当需要解决图中任意两点的最短路径时,Dijkstra则需要多次计算,而且,当图中存在负的边权重时,Dijkstra则显得无能为力。Floyd算法的提出很好的解决了这一问题,能一次求出任意两点的最短路径,并且边权重可正可负。
(1). 两点直接到达的距离最短。
(2). 两点之间通过1个或者1个以上节点连接到达的距离最短。
所以,如果是第一种情况,则可以在邻接矩阵中直接获取。如果是第二种情况,则需要依次判断以每个点为中间点连接起点和终点的最短距离。如果需要中间点的个数大于1,则将问题继续划分为其它终点和起点的问题。例如求AB间的最短距离,对于中间点有C,那么则需要判断
void getGraphicData(){//获取数据 ifstream in("data"); in>>vertexnum>>edgenum; //获取节点数和边数 int from,to; double w; // 初始化邻接矩阵和路径矩阵 while(in>>from>>to>>w){ weight[from][to] = w; path[from][to] = from; weight[from][from] = 0; path[from][from] = from; weight[to][to] = 0; path[to][to] = to; } } void floyd(){ for(int k = 0;k < vertexnum;k++) // 中间点变量 for(int i= 0;i < vertexnum;i++) // 起点变量 for(int j = 0;j < vertexnum;j++){ //终点变量 weight[i][j] = min(weight[i][j], weight[i][k] + weight[k][j]); path[i][j] = path[k][j]; } } } void displaypath(int source,int dest){ // 求取路径 stack<int> shortpath; int temp = dest; while(temp != source){ shortpath.push(temp); temp = path[source][temp]; } shortpath.push(source); cout<<"short distance:"<<weight[source][dest]<<endl<<"path:"; while(!shortpath.empty()){ cout<<shortpath.top()<<" "; shortpath.pop(); } }
结合下图:
(1). 初始化工作无非就是对图的邻接矩阵就行初始化,直接连接的边为常数权重,非直接连接的边初始化为无穷大,路径矩阵则是对点的前驱进行计算。
(2). 首先确定中间点
(3). 最后是确立路径,也就是起点和终点之间的中间点。
Floyd算法在实现时有一点需要注意,就是中间点的循环(这里时k)必须在外层,如果放在内层时,有的路径权重不会改变,这会对最后的结果产生错误,说起来比较难懂,可以手动模拟一下,就会发现这个问题。
小结
Dijkstra算法适合于单点的路径就算,而当需要任意两点间的最短路径时,Floyd算法比
- 最短路径算法(Dijkstra、Floyd)总结
- 最短路径算法 dijkstra + floyd + spfa 【记录 总结】
- 最短路径算法总结(Floyd,bellmen-ford,dijkstra,Spfa)
- 最短路径算法总结(Floyd,bellmen-ford,dijkstra,Spfa)
- Floyd算法与Dijkstra算法(最短路径)
- 图的最短路径(dijkstra算法/floyd算法)
- Dijkstra/Floyd-Warshall 最短路径算法
- 最短路径之Dijkstra+Floyd算法
- 最短路径之Dijkstra+Floyd算法
- 最短路径---Dijkstra/Floyd算法
- 最短路径算法(Dijkstra和Floyd)
- 最短路径算法介绍(转载)floyd+dijkstra
- 最短路径:(Dijkstra & Floyd)
- 最短路径(Dijkstra、Floyd)
- 最短路径(Dijkstra和Floyd)
- 最短路径&&Dijkstra&&Floyd
- 最短路径算法—Dijkstra算法与Floyd算法
- 最短路径算法 Dijkstra算法 Floyd算法 简述
- “虽然过了很多天但也要记录一下”的“头回儿找工作”--IOS岗
- Hello World!!!
- 不找C++的工作也要学C++
- Web Page Copy
- 读书笔记:Spark上数据的获取,处理与准备 下
- 最短路径算法(Dijkstra、Floyd)总结
- 机器学习数学基础之矩阵理论(二)
- 【洛谷】 P3374 【模板】树状数组 1
- Springboot 学习笔记 ①
- 创建 Rex-Ray volume
- 翻译:MLAPP(2.2节 概率论简要回顾)
- 机器学习之正则化
- eclipse或myeclipse中spring插件安装以及第一个spring程序
- Java定时周期任务