广度优先搜索双队列通用编程模板

来源:互联网 发布:iwatch软件排行 编辑:程序博客网 时间:2024/04/30 13:59

广度优先搜索主要用于解决求最短问题,如最短路径,最少变化步数问题等等,思想是从起点出发,按层遍历,直到搜索到目标或者已经搜索完全部区域。通常利用队列实现广度优先搜索,我这里使用的双队列法,用一个队列cur表示当前层,next表示由当前层扩展的下一层,用双队列有个好处是我们只需要定义一个全局变量level就能记录扩展的层数(即路径长度),如果要求输出具体最短路径的话,我们还需要利用一个unordered_map对象来保存路径树,为了避免搜索重复节点,我们需要标记已经搜索过的状态,这里利用unordered_set对象来保存已经搜索过的状态(注意如果unordered_map或unordered_set保存的是自定义的结构体时,我们需要自己定义==操作符合hash函数);我们还需要一个变量isfinsh来标记是否已经搜索到目标。

下面用一个具体的例子来说明广度优先搜索双队列编程模板的使用:


具体实现的程序如下:

#include "stdafx.h"#include <iostream>#include <vector>#include <queue>#include <unordered_map>#include <unordered_set>using namespace std;typedef struct node{int x;int y;node(int x=0,int y=0):x(x),y(y){};bool operator==(const node &rhs) const{return x==rhs.x && y==rhs.y;};}state;struct hash_func  //自定义的hash 函数  {  size_t operator()(const node &myNode) const  {  return 999*myNode.x+myNode.y;}  };  //根据father保存的路径树得到具体路径void findPath(vector<vector<int>> &result,unordered_map<state,state,hash_func> &father,state start,state child){state tmpState=child;while(tmpState.x!=start.x || tmpState.y!=start.y){int tmpPoint[2]={tmpState.x,tmpState.y};vector<int> tmpResult(tmpPoint,tmpPoint+2);result.push_back(tmpResult);tmpState=father[tmpState];}int tmpPoint[2]={tmpState.x,tmpState.y};vector<int> tmpResult(tmpPoint,tmpPoint+2);result.push_back(tmpResult);reverse(result.begin(),result.end());}vector<vector<int>> bfs(vector<vector<int>> &map,int &step,state &start,state &end){vector<vector<int>> result;if (map.size()<=0){return result;}if (start.x==end.x && start.y==end.y){return result;}int row=map.size();int col=map[0].size();int extend[4][2]={{0,1},{1,0},{0,-1},{-1,0}};  //按右-下-左-上顺时针方向扩展状态 //用于标记已经扩展过的状态,此处也可以利用一个二维bool数组,但是为了更具一般性,此处采用unordered_set//注意:要使用unordered_set,unordered_map,node需要有定义的==运算符和hash函数。unordered_set<state,hash_func> selected;unordered_map<state,state,hash_func> father;//用于记录路径树queue<state> cur;   //用于保存当前层的状态queue<state> next; //保存由cur扩展出的下一层状态int level=0;  //用于标记扩展的层数,可用于求最短路径长度bool isFinish=false;  //标记搜索是否结束cur.push(start);selected.insert(start);while(!cur.empty()&&!isFinish){++step;while(!cur.empty()&&!isFinish){state curState=cur.front();cur.pop();for(int i=0;i<4;++i){int tmpr=curState.x+extend[i][0];int tmpc=curState.y+extend[i][1];if (tmpc<0 ||tmpc>=row ||tmpr<0 || tmpr>=col)continue;if (map[tmpr][tmpc]==1)continue;state tmpState(tmpr,tmpc);if (tmpc==end.x && tmpr==end.y){isFinish=true;father[tmpState]=curState;break;}if (selected.count(tmpState)==0){next.push(tmpState);father[tmpState]=curState;selected.insert(tmpState);}}}swap(cur,next);}if (isFinish){findPath(result,father,start,end);}return result;}int _tmain(int argc, _TCHAR* argv[]){int inputArray[5][5]={{0,1,0,0,0},{0,1,0,1,0},{0,0,0,0,0},{0,1,1,1,0},{0,0,0,1,0}};vector<vector<int>> result;vector<vector<int>> map;for (int i=0;i<5;++i){vector<int> tmpMap(inputArray[i],inputArray[i]+5);map.push_back(tmpMap);}int step=0;state start(0,0);state end(4,4);result=bfs(map,step,start,end);cout<<"最少需要走 "<<step<<" 步"<<endl;for (int i=0;i<result.size();++i){cout<<"("<<result[i][0]<<","<<result[i][1]<<")"<<" ";}cout<<endl; return 0;}
程序运行结果如下:



0 0
原创粉丝点击