c++ 下实现多线程的双向dijkstra算法
来源:互联网 发布:申请淘宝网店的步骤 编辑:程序博客网 时间:2024/05/16 12:35
背景
上学期的通信网理论基础课上,双向dijkstra是一个选作的研究性课题,当时没做,这个假期有时间了准备写一个。写着写着发现既然是双向,两边同时运行肯定比来回切换的“伪同时”要更快,反正现在的CPU基本都是二核以上的。
开始想用fork()函数来着,后来发现windows下没有这玩意,又找到了CreateThread,结果成功实现。
大致思想
依旧是在网格地图中的寻路,由于要在两个方向上进行寻路,于是需要维护两个Priority_queue,而主体dijkstra不需要写两个,只要在传入参数中加一个方向标识即可。在判断寻路完毕上,我最终决定在visited上下手,即将原本的二元0-1 visited变为三元visited——0,正向访问完毕1,反向访问完毕1,当某方向探测到另一方向上的访问完毕标识时,即结束dijkstra,输出结果。与之相应的,控制dijkstra持续运行的不再是while而是递归。
实例代码
#include <iostream>#include <fstream>#include <queue>#include <vector>#include <windows.h> #define unit 10#define INF 10000#define forward 1#define back 0#define f_visit 6 //正方向访问标识 #define b_visit 7 //逆方向访问标识 using namespace std;class TPoint{public:int x;int y;};const int line=23;const int column=61;int dis_f[line][column];int dis_r[line][column];int visited[line][column];int map[line][column];TPoint pre[line][column];struct cmp_f{ bool operator()(TPoint a,TPoint b){ return dis_f[a.x][a.y]>dis_f[b.x][b.y]; } };struct cmp_r{ bool operator()(TPoint a,TPoint b){ return dis_r[a.x][a.y]>dis_r[b.x][b.y]; } };priority_queue<TPoint,vector<TPoint>,cmp_f> Q_front;priority_queue<TPoint,vector<TPoint>,cmp_r> Q_back;int Distance_Judgement(int ori_x, int ori_y, int next_x, int next_y){if(ori_x==next_x && abs(ori_y-next_y)==1)return unit;if(ori_y==next_y && abs(ori_x-next_x)==1)return unit;if(abs(ori_x-next_x)==1 && abs(ori_y-next_y)==1)return 1.4*unit;//对角线走法路经长为根号2倍单位 }bool Meeting_Detector(TPoint v, bool direction){//原理是两个方向上采用不同的visited记号,当某方向上探测到另一种visited记号时即停止探测返回结果 switch(direction){case forward:{if(visited[v.x][v.y]==b_visit){//cout<< "正方向探测到终结"<< endl; return TRUE;}elsereturn FALSE;break;} case back:{if(visited[v.x][v.y]==f_visit){//cout<< "逆方向探测到终结"<< endl;return TRUE;}elsereturn FALSE;break;}}}void Initia(TPoint ori, TPoint des){for(int i=0; i<line; i++)for(int j=0; j<column; j++){//二维数组不能用={0}这种简单方式初始化 pre[i][j].x = -1;dis_f[i][j] = INF;dis_r[i][j] = INF;visited[i][j] = 0;}ifstream fin("map.txt", ios::in);while(fin.good())for(int i=0; i<line; i++)for(int j=0; j<column; j++)fin>> map[i][j];dis_f[ori.x][ori.y] = 0;dis_r[des.x][des.y] = 0;}int Bi_Dijkstra(TPoint u, bool direction){int i, j;TPoint temp, next;if(Meeting_Detector(u, direction)){if(direction==forward){Sleep(5);cout<< "最短路径前半段长为"<< dis_f[u.x][u.y]<< "后半段长为"<< dis_r[u.x][u.y]<< endl;cout<< "总长为"<< dis_f[u.x][u.y]+dis_r[u.x][u.y]<< endl;cout<< "正向探测相遇点为"<< u.x<< ","<< u.y<< endl;} if(direction==back){Sleep(15);cout<< "最短路径前半段长为"<< dis_f[u.x][u.y]<< "后半段长为"<< dis_r[u.x][u.y]<< endl;cout<< "总长为"<< dis_f[u.x][u.y]+dis_r[u.x][u.y]<< endl;cout<< "逆向探测相遇点为"<< u.x<< ","<< u.y<< endl;} /*搜索区域染色输出 ofstream os("map_mirrir.txt"); if (os) { for (int i=0;i<line;i++) { for (int j=0;j<column;j++) os<< map[i][j]<<" "; os<<endl; } os<<endl;os<<endl;os<<endl; } else cerr<<"error"<<endl;*/Sleep(20); //执行快的那边等一会执行慢的,让它输出完 return 0;}if(direction==forward){visited[u.x][u.y] = f_visit;//map[u.x][u.y] = f_visit; //染色 }if(direction==back){visited[u.x][u.y] = b_visit;//map[u.x][u.y] = b_visit; //染色 }for(i=u.x-1; i<=u.x+1; i++){for(j=u.y-1; j<=u.y+1; j++){if(map[i][j]==0 || (i<0||i>=line) || (j<0||j>=column)){continue;}else if(map[i][j]!=0){int pace = Distance_Judgement(u.x, u.y, i, j);if(direction==forward && visited[i][j]!=f_visit){if(dis_f[i][j]==INF || dis_f[u.x][u.y]+pace < dis_f[i][j]){dis_f[i][j] = dis_f[u.x][u.y]+pace;pre[i][j].x = u.x; pre[i][j].y = u.y; temp.x = i; temp.y = j;//visited[i][j] = f_visit; //这个在我上一个常规dijkstra算法里没有注释掉,想了想其实应该注释掉的,虽然对结果没影响 Q_front.push(temp);}}if(direction==back && visited[i][j]!=b_visit){if(dis_r[i][j]==INF || dis_r[u.x][u.y]+pace < dis_r[i][j]){dis_r[i][j] = dis_r[u.x][u.y]+pace;pre[i][j].x = u.x; pre[i][j].y = u.y; temp.x = i; temp.y = j;//visited[i][j] = b_visit; //同上 Q_back.push(temp);}}}}}switch(direction){case forward:{next = Q_front.top();Q_front.pop();Sleep(1); //因为是并发执行,而且速度很快,不缓冲一下程序就报错,而且也看不出并发效果了 Bi_Dijkstra(next, forward);break;}case back:{next = Q_back.top();Q_back.pop();Sleep(1);//缓冲 Bi_Dijkstra(next, back);break;}}}DWORD WINAPI ThreadProc(LPVOID lpParameter){ //子线程 TPoint ori, temp1;ori.x = 0; ori.y = 0; Q_front.push(ori); temp1 = Q_front.top(); Q_front.pop(); Bi_Dijkstra(temp1, forward);}int main(){TPoint ori, des, temp2;ori.x = 0; ori.y = 0;des.x = 22; des.y = 60;Initia(ori, des);HANDLE thread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);//子线程创建 CloseHandle(thread);//结束子线程 Q_back.push(des);//主线程部分 temp2 = Q_back.top(); Q_back.pop(); Bi_Dijkstra(temp2, back); return 0;}
0 0
- c++ 下实现多线程的双向dijkstra算法
- C++Dijkstra算法实现
- Dijkstra 算法的 C/C++ 实现
- Dijkstra算法的简单实现(C++)
- POX控制器下Dijkstra算法的实现
- Dijkstra算法 c语言实现
- Dijkstra算法 c/c++实现
- dijkstra算法C语言实现
- c/c++ Dijkstra算法实现
- Dijkstra算法的实现
- Dijkstra算法的实现
- dijkstra算法的实现。
- Dijkstra算法的实现
- 双向广搜的DIJKSTRA算法--简易的北京地铁导航实现
- 数据结构(C#)--Dijkstra 算法的最小路径的实现
- 配合Dijkstra算法的Hash表实现文件C语言
- 配合Dijkstra算法的二叉堆实现文件C语言
- Dijkstra 算法+Heap堆的完整c实现源码
- CopyOnWriteArrayList与java内存模型
- ZZULIOJ-【不是匹配】
- Java虚拟机学习 - 对象访问
- Softmax Regression
- Python实现FTP暴力破解
- c++ 下实现多线程的双向dijkstra算法
- 最大化最小值 POJ2456 3273
- Java虚拟机学习 - 垃圾收集算法
- spring总结
- HTML 学习笔记二
- C++之lambda
- springMVC
- Java虚拟机学习 - 垃圾收集器
- Manachor算法---求最长回文字串