双向广度优先搜索
双向广度优先搜索
双向广度优先搜索是对广搜算法的一种扩展。广搜以起点以广度优先的顺序不断扩展,直到遇到目的节点。
而双向广搜算法从两个方向开展广搜,一个从起点,另一个从终点。
直到一个扩展队列中出现了另一个队列中已经扩展了的点,也就是说两个扩展方向出现了交点。
双向广搜相对于广搜算法来说,由于采用了双向同时扩展的方式,搜索树的宽度明显减宽,时间和空间复杂度都明显提高。
假设一个节点能扩展n个节点,扩展m层,单向广搜扩展出的数量就是 (1 - nm) ⁄ ( 1 - n )
而双向广搜同样扩展m层,总结点数为 ( 1 - nm/2) / ( 1 - n ) ,在数据范围较大的时候,优势就体现出来了
1 void dbfs{ 2 将起点放入队列q1,目标节点放入q2 3 while(两个队列均未空且未发现路径){ 4 如果q1中节点比q2中少,则扩展q1,否则扩展q1 5 } 6 if(未发现路径){ 7 如果q1未空,不断扩展q1为空或发现路径 8 如果q2未空,不断扩展q2未空或发现路径 9 } 10 }
现在我插入一段关于八数码问题的双向广搜代码
1 inline bool DBFs(int status) 2 { 3 \\寻找初始状态status到目标的路径,找不到则返回false 4 int newstatus; 5 set<int> expanded[2];\\两个队列判重 6 for(int i=0;i<2;i++){ 7 qhead[i]=0;qtail[i]=1; 8 } 9 myqueue[0][0]=Node(status,-1,0); 10 expanded[0].insert(status); 11 myqueue[1][0]=Node(goalStatus,-1,0); 12 expanded[1].insert(goalStatus); 13 while(qhead[0]!=qtail[0]&&qhead[1]!=qtail[1])\\两队均不为空 14 { 15 int qno;\\本次要扩展的队列 16 if(qhead[0]==qtail[0]) qno=1; 17 else if(qhead[1]=qtail[1]) 18 qno=0; 19 else{//比较两队元素个数 20 if(qtail[0]-qhead[0]<qtail[1]-qhead[1]) 21 qno=0; 22 else qno=1; 23 } 24 int vqno=1-qno;//另一队列 25 status=myqueue[qno][qhead[qno]].Status ; 26 if(expanded[vqno].find(status)!=expanded[vqno].end() ){//在另一个队列扩展过,路径找到 matchings=status; 27 matchingq=qno; 28 return true; 29 } 30 else{ 31 for(int i=0;i<4;i++){//尝试4种移动 32 newstatus=New(status,move[i]); //表示移动后的新状态是否可行 33 if(newstatus==-1) 34 continue;//否,下一种 35 if(expanded[qno].find(newstatus)!=expanded[qno].end() ) 36 continue;//以扩展过,则不能入队 37 expanded[qno].insert(newstatus); 38 myqueue[qno][qtail[qno]]=Node(newstatus,qhead[qno],moves[i]);//moves[]表示4种移动 39 qtail[qno]++; 40 } 41 qhead[qno]++; 42 } 43 } 44 return false; 45 }
其中 goalstatus 为目标状态 matchings为双向碰到的状态 matchingq碰到的那个队列
-end-
强行退出函数 exit(0)