Dijkstra算法实现非负权值最短路径的求解(另用小根堆进行优化)
2012-12-09 14:25
531 查看
利用Dijkstra算法求解非负权值的最小值,基本思想是,进行n-1轮的循环,每一轮都是:求出单边条件下起始结点v0到其他各结点的最短距离,并将邻接到的这个点v1标为“已处理过”,然后再以v1作为中转,找到跟v1距离最近的剩下的顶点v2,接着比较dist[v2]的值和dist[v1]+weight[v1][v2],如果dist[v2]较大,则将dist[v2]改写为dist[v1]+weight[v1][v2]。
基本实现如下:
但分析上面的代码可知,在找跟起始点最近的结点时,重复比较了很多次,我们可以用优先队列或者一个小根堆来帮助我们快速地找到跟其实结点最近的那个结点。
基本实现如下:
#include <iostream> #include <memory.h> using namespace std; const int MaxSize=10; int arr[MaxSize][MaxSize]; int dist[MaxSize]; int numNode=0; //记录图中的结点个数 //邻接矩阵的初始化 void createArr() { //当边的长度为无穷大时输入一个自认为较大的数 cin>>numNode; for(int i=0;i<numNode;++i) for(int j=0;j<numNode;++j) cin>>arr[i][j]; } //非负权值的最短路径 void Dijkstra(int v0) { memset(dist,0,sizeof(dist)); //初始化v0到各结点的路径值 for(int i=0;i<numNode;++i) dist[i]=arr[v0][i]; int pos=0; arr[v0][v0]=1; //将v0的访问标记置为1 //做numNode-1次求v0到各结点的操作 for(int i=0;i<numNode-1;++i) { int min=32767; //找出单边的情况下离v0最近的结点 for(int k=0;k<numNode;++k) { if((dist[k]<min)&&(arr[k][k]!=1)) { pos=k; min=dist[k]; } } arr[pos][pos]=1; //将该结点访问标记置为1 //以pos结点为中转,当if条件满足时改写其他结点到v0的距离 for(int j=0;j<numNode;++j) { if((arr[j][j]!=1)&&(arr[pos][j]+min<dist[j])) dist[j]=arr[pos][j]+min; } } //输出各结点到起始结点的最短路径 for(int i=0;i<numNode;++i) cout<<dist[i]<<" "; cout<<endl; } int main() { createArr(); Dijkstra(0); }
但分析上面的代码可知,在找跟起始点最近的结点时,重复比较了很多次,我们可以用优先队列或者一个小根堆来帮助我们快速地找到跟其实结点最近的那个结点。
#include <iostream> #include <memory.h> using namespace std; /***************************堆**********************/ struct Heap { int link; //表示初始结点临接到的顶点 int dist;//权值 } heap[60]; //下滑操作 void siftDown(int start,int end) { //将start号结点向下调整直到end int i=start,j=2*i; heap[0]=heap[i]; //用heap[0]来临时保存i结点的值 while(j<=end) { //有右孩子并且右孩子比左孩子小时,或者当优先级相同并且j号结点后出现时将j保存右孩子 if(j<end&&heap[j].dist>heap[j+1].dist) ++j; //比j号结点小时,不需调整 if(heap[0].dist<heap[j].dist) break; else { //向下调整 heap[i]=heap[j]; i=j; j=2*j; } } heap[i]=heap[0]; } //向上调整的函数 //将结点start调整到根结点1为止 void siftUp(int start) { int j=start,i=j/2; heap[0]=heap[j]; while(j>0) { //优先级相同时,numID小的先输出 if(heap[i].dist<heap[0].dist) break; else { //向上调整工作 heap[j]=heap[i]; j=i; i=i/2; } } heap[j]=heap[0]; } //插入操作的实现 bool insert(int& num,Heap& temp) { ++num; heap[num]=temp; siftUp(num); return true; } //删除操作 bool removeMin(int& num,Heap& temp) { if(0==num) return false; //将根的信息通过参数返回 temp=heap[1]; heap[1]=heap[num]; //填补树根 --num; siftDown(1,num); //将根结点下滑到尾部 return true; } /*******************************图****************************/ const int MaxSize=10; int arr[MaxSize][MaxSize]; //存放邻接矩阵的数组 int dist[MaxSize]; //到起始点长度的数组 int numNode=0; //记录图中的结点个数 //创建邻接矩阵 void createArr() { //当边的长度为无穷大时输入一个自认为较大的数 cin>>numNode; for(int i=0;i<numNode;++i) for(int j=0;j<numNode;++j) cin>>arr[i][j]; } //非负权值的最短路径 void Dijkstra(int v0) { memset(dist,0,sizeof(dist)); //初始化v0到各结点的路径值 for(int i=0;i<numNode;++i) dist[i]=arr[v0][i]; arr[v0][v0]=1; //将v0的访问标记置为1 int num=0; //堆的大小的初始化 Heap temp; //做numNode-1次求v0到各结点的操作 for(int i=0;i<numNode-1;++i) { //将没访问过的结点和权值压入堆中 for(int k=0;k<numNode;++k) { if(arr[k][k]!=1) { temp.link=k; temp.dist=dist[k]; insert(num,temp); } } //通过堆得到单边的情况下离v0最近的结点 if(!removeMin(num,temp)) return; int pos=temp.link; int min=temp.dist; arr[pos][pos]=1; //将该结点访问标记置为1 //以pos结点为中转,依条件改写其他结点到v0的距离 for(int j=0;j<numNode;++j) { if((arr[j][j]!=1)&&(arr[pos][j]+min<dist[j])) { dist[j]=arr[pos][j]+min; //将修改后的关系压入堆中 temp.link=j; temp.dist=dist[j]; insert(num,temp); } } } //输出起始点v0与各个顶点之间的最短路径 for(int i=0;i<numNode;++i) cout<<dist[i]<<" "; cout<<endl; } int main() { createArr(); Dijkstra(0); }
相关文章推荐
- 单源最短路径问题(dijkstra算法 及其 优化算法(优先队列实现))
- 求图中最短路径算法之Dijkstra算法——C++实现并优化
- Python使用Dijkstra算法实现求解图中最短路径距离问题详解
- poj 1125 Stockbroker Grapevine dijkstra算法实现最短路径
- 利用MPI求解全源最短路径的并行算法实现
- 最短路径算法之Dijkstra算法(java实现)
- Dijkstra最短路径求解(不考虑权值为负的情况)
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路);Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- Dijkstra算法实现单源最短路径
- 图论:最短路径搜索--Dijkstra算法(c代码实现)
- 最短路径问题——Dijkstra算法(C++实现)
- HDOJ 2544 最短路(最短路径 dijkstra算法,SPFA邻接表实现,floyd算法)
- 无向图的最短路径求解算法之——Dijkstra算法【转】
- 【算法——Python实现】有权图求单源最短路径Dijkstra算法
- 单源最短路径 dijkstra算法实现
- poj 1125 Stockbroker Grapevine dijkstra算法实现最短路径
- HDU-3790 最短路径问题(两个权值,Dijkstra,(含堆优化))
- (阶段三 dijkstra算法温习1.5)HDU 2680 Choose the best route(使用dijkstra算法求解多源起点的最短路径问题)
- 数据结构与算法——最短路径Dijkstra算法的C++实现
- 无向图的最短路径求解算法之——Dijkstra算法(二)