Dijkstra最短路径算法(SPF)
2012-12-04 22:42
204 查看
算法描述:
Dijkstra算法是一种求单源最短路的算法,即从一个点开始到所有其他点的最短路。其基本原理是:每次新扩展一个距离最短的点,更新与其相邻的点的距离。当所有边权都为正时,由于不会存在一个距离更短的没扩展过的点,所以这个点的距离永远不会再被改变,因而保证了算法的正确性。不过根据这个原理,用Dijkstra求最短路的图不能有负权边,因为扩展到负权边的时候会产生更短的距离,有可能就破坏了已经更新的点距离不会改变的性质。
如果用本算法求一个图中全部的最短路,则要以每个点为源调用一次Dijkstra算法。
使用条件与限制:
有向图和无向图都可以使用本算法,无向图中的每条边可以看成相反的两条边。
用来求最短路的图中不能存在负权边。(可以利用拓扑排序检测)
算法流程:
在以下说明中,s为源,w[u,v]为点u和v之间的边的长度,结果保存在dist[]
初始化:源的距离dist[s]设为0,其他的点距离设为无穷大,同时把所有的点的状态设为没有扩展过。
循环n-1次:
在没有扩展过的点中取一距离最小的点u,并将其状态设为已扩展。
对于每个与u相邻的点v,执行Relax(u,v),也就是说,如果dist[u]+w[u,v]<dist[v],那么把dist[v]更新成更短的距离dist[u]+w[u,v]。此时到点v的最短路径上,前一个节点即为u。
结束。此时对于任意的u,dist[u]就是s到u的距离。
复杂度分析:
最简单的实现方法就是,在每次循环中,再用一个循环找距离最短的点,然后用任意的方法更新与其相邻的边,时间复杂度显然为
对于空间复杂度:如果只要求出距离,只要n的附加空间保存距离就可以了(距离小于当前距离的是已访问的节点,对于距离相等的情况可以比较编号或是特殊处理下)。如果要求出路径则需要另外V的空间保存前一个节点,总共需要2n的空间。
下面具体的代码实现:
下面是运行截图:
Dijkstra算法是一种求单源最短路的算法,即从一个点开始到所有其他点的最短路。其基本原理是:每次新扩展一个距离最短的点,更新与其相邻的点的距离。当所有边权都为正时,由于不会存在一个距离更短的没扩展过的点,所以这个点的距离永远不会再被改变,因而保证了算法的正确性。不过根据这个原理,用Dijkstra求最短路的图不能有负权边,因为扩展到负权边的时候会产生更短的距离,有可能就破坏了已经更新的点距离不会改变的性质。
如果用本算法求一个图中全部的最短路,则要以每个点为源调用一次Dijkstra算法。
使用条件与限制:
有向图和无向图都可以使用本算法,无向图中的每条边可以看成相反的两条边。
用来求最短路的图中不能存在负权边。(可以利用拓扑排序检测)
算法流程:
在以下说明中,s为源,w[u,v]为点u和v之间的边的长度,结果保存在dist[]
初始化:源的距离dist[s]设为0,其他的点距离设为无穷大,同时把所有的点的状态设为没有扩展过。
循环n-1次:
在没有扩展过的点中取一距离最小的点u,并将其状态设为已扩展。
对于每个与u相邻的点v,执行Relax(u,v),也就是说,如果dist[u]+w[u,v]<dist[v],那么把dist[v]更新成更短的距离dist[u]+w[u,v]。此时到点v的最短路径上,前一个节点即为u。
结束。此时对于任意的u,dist[u]就是s到u的距离。
复杂度分析:
最简单的实现方法就是,在每次循环中,再用一个循环找距离最短的点,然后用任意的方法更新与其相邻的边,时间复杂度显然为
对于空间复杂度:如果只要求出距离,只要n的附加空间保存距离就可以了(距离小于当前距离的是已访问的节点,对于距离相等的情况可以比较编号或是特殊处理下)。如果要求出路径则需要另外V的空间保存前一个节点,总共需要2n的空间。
下面具体的代码实现:
#pragma once #include<iostream> #include<fstream> #include"F:\QQPCmgr\documents\visual studio 2010\Projects\Graph\Graph_matrix\GraphAdjMatrix.h" using namespace std; template<class T, class E> void DijkstraAlgorithm(GraphAdjMatrix<T,E> &targetG, const T &beginVertex, E dist[], int path[]) { int verticesNum = targetG.GetVerticesNum(); //获取图顶点数目 int beginIdx = targetG.GetVerticesPos(beginVertex); //获取源顶点索引值(在这里都是用顶点索引值代表顶点的) bool *state = new bool[verticesNum]; //一个状态值数组,用来表示已求得的最短路径顶点集 E weigth_temp, minWeight; //辅助求最短路径变量 E maxWeightFlag = targetG.GetMaxWeight(); //获取图中约定好的代表顶点之间不可达的权值标示 for(int i = 0; i < verticesNum; i++) //循环用来做初始化信息 { dist[i] = targetG.GetWeight(beginIdx, i); //dist[]数组中最初存放源点能直接到达的点的边权值(这个以后会根据算法的进行慢慢更新的) state[i] = false; //把所有的状态值都置为false 表示都没有求出最短路径 if((i != beginIdx) && (dist[i] != maxWeightFlag)) //不等于源点并且源点与顶点i之间有边 { path[i] = beginIdx; //pre = path[i]表示:能最近到达i顶点的上一步是pre(算法只着眼于能到达本顶点路径长度最短的上一个顶点,通过回溯可以一步一步的回溯到源点) } else { path[i] = -1; //表示:到达顶点i路径长度最短的上一个顶点不存在,意味着不存在源点到达顶点i最短路径 } } state[beginIdx] = true; //算法起始:将源点放入已求得最短路径顶点集合中 dist[beginIdx] = 0; //从源点到达源点的边权值为0 for(int count = 0; count < verticesNum-1; count++) //总共循环图定点数目-1次 { minWeight = maxWeightFlag; int nextIdx; //此索引记录:当前dist[]中值最小的那一个(通过循环实现) for(int i = 0; i < verticesNum; i++) { if((state[i] == false) && (dist[i] < minWeight)) { minWeight = dist[i]; nextIdx = i; } } state[nextIdx] = true; //可以认为:就目前来看源点到达nextIdx的路径是最短的,将其放入状态数组中 //站在nextIdx顶点的角度来看,是否能借助于我,使得源点到达其他顶点的路径会更短呢?下面是搜索与判断,更新 for(int k = 0; k < verticesNum; k++) { weigth_temp = targetG.GetWeight(nextIdx, k); //如果确实通过nextIdx顶点使得源点到达顶点k的路径更小了,执行下面if语句 if((state[k] == false)&&(weigth_temp != maxWeightFlag)&&(dist[nextIdx] + weigth_temp < dist[k])) { dist[k] = dist[nextIdx] + weigth_temp; path[k] = nextIdx; //这时要修改能够最短到达顶点k的上一个顶点 } } }//外层大循环 } template<class T, class E> void PrintShortestPath(GraphAdjMatrix<T,E> &targetG, const T &beginVertex, E dist[], int path[]) { int begVtxNum = targetG.GetVerticesPos(beginVertex); //获取源点索引 int verticesNum = targetG.GetVerticesNum(); int temp, count; int *tempDist = new int[verticesNum]; //用来存储源点到达其他的任意一个顶点的路径信息(存储的仍然是顶点索引) for(int vtxnum = 0; vtxnum < verticesNum; vtxnum++) //搜索所有的顶点 { if(vtxnum != begVtxNum) //不能对源点输出最短路径 { temp = vtxnum; count = 0; while(temp != begVtxNum) { tempDist[count++] = temp; //先把目的顶点vtxnum的索引放入辅助数组tempDist[]中 temp = path[temp]; //回溯找到源点 } cout<<"顶点:<"<<targetG.GetVertex(vtxnum)<<">的最短路径:"<<beginVertex<<" "; while(count > 0) { cout<<targetG.GetVertex(tempDist[--count])<<" "; //对辅助数组进行逆向输出 } cout<<"最短路径长度为:"<<dist[vtxnum]<<endl; } } delete []tempDist; }
下面是运行截图:
相关文章推荐
- Dijkstra最短路径算法
- PAT 数据结构 06-图5. 旅游规划(25)Dijkstra最短路径算法
- Node:最短路径算法之Dijkstra
- 算法实现Java之最短路径迪杰斯特拉(Dijkstra)
- 最短路径算法 java实现 - Dijkstra
- 最短路径之迪杰斯特拉(Dijkstra)算法
- 图论之Dijkstra最短路径算法
- 最短路径(Dijkstra)算法 之 .Net 4.0 Parallel 实现
- DIJKSTRA最短路径算法
- Dijkstra算法求单源最短路径
- Dijkstra算法求单源最短路径Java实现
- 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson,无一幸免
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 4.Dijkstra单点最短路径算法 迪杰斯特拉
- 贪心算法 - 单源最短路径 Dijkstra
- 算法:最短路径之迪杰斯特拉(Dijkstra)算法
- Dijkstra's Shortest Path Algorithm(最短路径算法)
- 图算法之再续最短路径(Dijkstra)
- [置顶] 【matlab dijkstra单源最短路径算法】dijkstra单源最短路径算法实现
- hdu 1874 最短路径 dijkstra 和floyd 算法