博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
双向搜索算法
阅读量:4044 次
发布时间:2019-05-24

本文共 6724 字,大约阅读时间需要 22 分钟。

搜索算法一直是ai中的核心讨论内容.基本都是从效率考虑,当然数量级很小的话或者格局普通,没什么差别?但一到涉及到特殊的情况,恐怕就分出优劣了;当然,不同的算法,可能适合不同的场合.

    此处讨论一下双向搜索算法,但不涉及到算法思想的揉和,此处就不讲a*的思想考虑进去

    双向搜索算法:较之普通搜索,搜索面积是1/2;

在一方出现闭环现象时,可以很快结束搜索,但其他算法,估计要把源闭环中所有节点搜尽;

此处以c语言来实现双向搜索算法有兴趣的朋友,可以考虑将a*算法思想加入,也许效率更好不过如你加入的话,敬请让我学习一下

   

typedef struct _POINT

{

       int nx;

       int ny;

}POINT;

 

typedef struct _WORLDUNIT

{

       BYTE nColorIndex;//颜色索引

   

       boolean bClear;  //

    boolean bFind;  //是否已经查找过了

       POINT Father; ///正向,逆向求解路径

       int nChild;//表示数目了.

       POINT CHILD[4];///正向,逆向求解路径

}WorldUnit;

 

void ResetPathData(AIGoogleApp * pMe)//重置搜索路径的所有数据….

{

       int x,y;

    for(x=0;x<Line_Num;x++)

       {

              for(y=0;y<Col_Num;y++)

              {

                     pMe->Cell[x][y].nChild=0;

                  pMe->Cell[x][y].Father.nx=NOVALUE;

                     pMe->Cell[x][y].Father.ny=NOVALUE;      

                     pMe->Cell[x][y].bFind =FALSE; 

                     pMe->Cell[x][y].bClear=FALSE;          

              }

       }   

       //已保存数据也要重置了.

}

 

 

void InitFindData(AIGoogleApp * pMe)//初始化搜索的数据了….

{

       pMe->nSelOld=1;  ///正在目标搜索的节点数目

       pMe->SelOld[0].nx =pMe->nSelx; ///正在目标搜索的节点

       pMe->SelOld[0].ny =pMe->nSely;  

       pMe->Cell[pMe->nSelx][pMe->nSely].bFind=TRUE;  标志为查找过了

       pMe->nSelNew=0; //新添加的可搜索节点个数

 

       pMe->nAimOld=1; ///正在目标搜索的节点数目,主要是双向的问题,才这样定义.

       pMe->AimOld[0].nx =pMe->nAimx;

       pMe->AimOld[0].ny =pMe->nAimy;  

       pMe->Cell[pMe->nAimx][pMe->nAimy].bFind=TRUE;

       pMe->nAimNew=0;

}

 

static boolean FindGoodPath(AIGoogleApp * pMe)

{

       int x,y;//用于自身周围的数据了.

       int m,n;//临时变量

 

       ResetPathData(pMe);//重置数据,然后开始了.

 

       InitFindData(pMe); //重置查找数据了.

       //从两个点出发查找问题.

       while((pMe->nSelOld!=0)&&(pMe->nAimOld!=0))//任意一个正在搜索的节点集为空的话,停止搜索

       {

              //处理了,先处理选中的,再处理目的的.

              //逐个判断算了

              /*

              if(pMe->nSelOld==0)

              {

             

              }

              if(pMe->nAimOld==0)

              {

                    

              }

        */

              while(pMe->nSelOld!=0)//将该外圈全部查找完毕才算结束了.

              {

                     //首先不可能是了.原因:是的话就不可能调用查找路径了.

            //把已经浏览过得给毖掉.哈哈,就可以了.                  

                    

                     x=pMe->SelOld[pMe->nSelOld-1].nx;

                     y=pMe->SelOld[pMe->nSelOld-1].ny;

                    

                     pMe->Cell[x][y].bFind=TRUE;              

           

                     //上面的判断

                     m=x-1;

                     n=y;

                     if(m>=0)

                     {

 

                            if(FindOrAdd(pMe,m,n,x,y,0,TRUE))//检测是否查找到了,呵呵

                            {

                                   return TRUE;

                            }

                     }

                    

                     //下面的判断

                     m=x+1;

                     n=y;

                     if(m<Line_Num)

                     {

                            if(FindOrAdd(pMe,m,n,x,y,1,TRUE)) //检测是否查找到了,呵呵

                            {

                                   return TRUE;

                            }

                     }

             

                     //左面的判断

                     m=x;

                     n=y-1;

                     if(n>=0)

                     {

                            if(FindOrAdd(pMe,m,n,x,y,2,TRUE)) //检测是否查找到了,呵呵

                            {

                                   return TRUE;

                            }

                     }

             

                     //右面的判断

                     m=x;

                     n=y+1;

                     if(n<Col_Num)

                     {

                            if(FindOrAdd(pMe,m,n,x,y,3,TRUE)) //检测是否查找到了,呵呵

                            {

                                   return TRUE;

                            }

                     }

                    

                     pMe->nSelOld--;

                    

              }

              //然后新的赋给老的

        //新的赋给老的             

              NewToOld(pMe,FALSE);//将新生成的搜索集赋给老的了

             

        while(pMe->nAimOld!=0)//将该外圈全部查找完毕才算结束了.

              {

                     //首先不可能是了.原因:是的话就不可能调用查找路径了.

            //把已经浏览过得给毖掉.哈哈,就可以了.                  

                    

                     x=pMe->AimOld[pMe->nAimOld-1].nx;

                     y=pMe->AimOld[pMe->nAimOld-1].ny;

                    

                     pMe->Cell[x][y].bFind=TRUE;              

           

             

                     //上面的判断

                     m=x-1;

                     n=y;

                     if(m>=0)

                     {

 

                            if(FindOrAdd(pMe,m,n,x,y,0,FALSE))

                            {

                                   return TRUE;

                            }

                     }

             

                     //下面的判断

                     m=x+1;

                     n=y;

                     if(m<Line_Num)

                     {

                            if(FindOrAdd(pMe,m,n,x,y,1,FALSE))

                            {

                                   return TRUE;

                            }

                     }

                    

                     //左面的判断

                     m=x;

                     n=y-1;

                     if(n>=0)

                     {

                            if(FindOrAdd(pMe,m,n,x,y,2,FALSE))

                            {

                                   return TRUE;

                            }

                     }

                    

                     //右面的判断

                     m=x;

                     n=y+1;

                     if(n<Col_Num)

                     {

                            if(FindOrAdd(pMe,m,n,x,y,3,FALSE))

                            {

                                   return TRUE;

                            }

                     }

                    

                     pMe->nAimOld--;

                    

              }

        //然后新的赋给老的

             

              NewToOld(pMe,TRUE);

       }

       return FALSE;

}

boolean FindOrAdd(AIGoogleApp * pMe,int m,int n,int x,int y,int nChild,boolean bInAim)

{

    

       POINT ToCheck;

 

       if(pMe->Cell[m][n].nColorIndex!=0)

       {

              return FALSE;

       }

             

       ToCheck.nx=m;

       ToCheck.ny=n;

       if(CheckFind(pMe,ToCheck,bInAim))

       {

              pMe->PosFind.nx=ToCheck.nx ;

              pMe->PosFind.ny=ToCheck.ny ;

              ConStructPath(pMe,x,y,bInAim);//转过去的是找到点的准父 接点了.但目前尚无父子关系.

              return TRUE;

       }

       else

       {

              if(pMe->Cell[m][n].bFind==TRUE)

                     return FALSE;

              if(bInAim)                   

              {

                     pMe->Cell[x][y].CHILD[nChild].nx=m;//将其儿子进行赋值  

                     pMe->Cell[x][y].CHILD[nChild].ny=n;

                    

                     pMe->SelNew[pMe->nSelNew].nx=m;

                     pMe->SelNew[pMe->nSelNew].ny=n;

                    

                     pMe->nSelNew++;//儿子数目增加

                    

                     pMe->Cell[m][n].Father.nx=x;//儿子指向父亲

                     pMe->Cell[m][n].Father.ny=y;

                     pMe->Cell[m][n].bFind=TRUE;//设置为已经找到过了.

              }

              else

              {

                     pMe->Cell[x][y].CHILD[nChild].nx=m;//将其儿子进行赋值  

                     pMe->Cell[x][y].CHILD[nChild].ny=n;

                    

                     pMe->AimNew[pMe->nAimNew].nx=m;

                     pMe->AimNew[pMe->nAimNew].ny=n;

                    

                     pMe->nAimNew++;//儿子数目增加

                    

                     pMe->Cell[m][n].Father.nx=x;//儿子指向父亲

                     pMe->Cell[m][n].Father.ny=y;

                     pMe->Cell[m][n].bFind=TRUE;//设置为已经找到过了.

              }

       }                         

       //检测是否找到了.如果找到退出.                                  

       //如果没找到呢,就添加到新的里面去

       //进行处理

      

       return FALSE;

}

 

boolean CheckFind(AIGoogleApp * pMe,POINT ToCheck,boolean bInAim)

{

       int x;      

       if(bInAim)//如果在目标里查找

       {

       

              for(x=0;x<pMe->nAimOld;x++)

              {

                     if(IsEqual(pMe,ToCheck,pMe->AimOld[x]))

                     {

                         

                            return TRUE;

                     }

              }

       }

       else

       {

              for(x=0;x<pMe->nSelOld;x++)

              {

                     if(IsEqual(pMe,ToCheck,pMe->SelOld[x]))

                     {

                            return TRUE;

                     }

              }

       }

       return FALSE;

}

 

///

boolean IsEqual(AIGoogleApp * pMe,POINT Check1,POINT Check2)

{

       if((Check1.nx==Check2.nx)&&(Check1.ny==Check2.ny))

              return TRUE;

       else

              return FALSE;     

}

//

void NewToOld(AIGoogleApp * pMe,boolean bAim)

{

       int x;

       if(bAim)

       {

              pMe->nAimOld=0;

             

              for(x=0;x<pMe->nAimNew;x++)

              {

                     pMe->AimOld[pMe->nAimOld].nx =pMe->AimNew[x].nx;

                     pMe->AimOld[pMe->nAimOld].ny =pMe->AimNew[x].ny;

                     pMe->nAimOld++;

                    

              }

              pMe->nAimNew=0;

       }

       else

       {

              pMe->nSelOld=0;

             

              for(x=0;x<pMe->nSelNew;x++)

              {

                     pMe->SelOld[pMe->nSelOld].nx =pMe->SelNew[x].nx;

                     pMe->SelOld[pMe->nSelOld].ny =pMe->SelNew[x].ny;

                     pMe->nSelOld++;                   

              }

              pMe->nSelNew=0;

       }

}

///

void ConStructPath(AIGoogleApp * pMe,int x,int y,boolean bAim)

{

       int x1,y1,m,n;

       int nChildx,nChildy;

       //转过去的是找到点的准父 接点了.但目前尚无父子关系.

     PathToSel(pMe,x,y,bAim);

        PathToAim(pMe,x,y,bAim);

        if(bAim)//连接起来了//

        {

               pMe->Cell[x][y].nChild=1; 

               pMe->Cell[x][y].CHILD[0].nx=pMe->PosFind.nx ;

               pMe->Cell[x][y].CHILD[0].ny=pMe->PosFind.ny ; 

        }

        else

        {

               pMe->Cell[pMe->PosFind.nx][pMe->PosFind.ny].CHILD[0].nx=x;

               pMe->Cell[pMe->PosFind.nx][pMe->PosFind.ny].CHILD[0].ny=y;

               pMe->Cell[pMe->PosFind.nx][pMe->PosFind.ny].nChild=1;

        }

 

        x1=pMe->nSelx;

        y1=pMe->nSely;

 

     while((x1!=pMe->nAimx)||(y1!=pMe->nAimy))

        {

        

               if((pMe->Cell[x1][y1].CHILD[0].nx==x1)&&(pMe->Cell[x1][y1].CHILD[0].ny==y1))

               {

                      break;

               }

 

               nChildx=pMe->Cell[x1][y1].CHILD[0].nx;

               nChildy=pMe->Cell[x1][y1].CHILD[0].ny;

               

               m=pMe->Cell[x1][y1].CHILD[0].nx;

               n=pMe->Cell[x1][y1].CHILD[0].ny;

               x1=m;

               y1=n;

        }

 

}

///

void PathToSel(AIGoogleApp * pMe,int x,int y,boolean bAim)

{

       //转过去的是找到点的准父 接点了.但目前尚无父子关系.

       int m,n;

       if(bAim)//在目标集中找到的话

       {

              //指向选择者的.

              while(pMe->Cell[x][y].Father.nx!=NOVALUE)

              {

                     m=pMe->Cell[x][y].Father.nx;

                     n=pMe->Cell[x][y].Father.ny;

                     pMe->Cell[m][n].CHILD[0].nx=x;

                     pMe->Cell[m][n].CHILD[0].ny=y;

                     pMe->Cell[m][n].nChild=1; 

                     x=m;

                     y=n;

              }

       }

       else

       {

              x=pMe->PosFind.nx;

              y=pMe->PosFind.ny;

              while(pMe->Cell[x][y].Father.nx!=NOVALUE)

              {

           

                     m=pMe->Cell[x][y].Father.nx;

                     n=pMe->Cell[x][y].Father.ny;

                     pMe->Cell[m][n].CHILD[0].nx=x;

                     pMe->Cell[m][n].CHILD[0].ny=y;

                     pMe->Cell[m][n].nChild=1;

                     x=m;

                     y=n;

              }

       }

 

}

void PathToAim(AIGoogleApp * pMe,int x,int y,boolean bAim)

{

       //转过去的是找到点的准父 接点了.但目前尚无父子关系.

       int m,n;

       if(bAim)

       {

              //指向选择者的.

 

              x=pMe->PosFind.nx;

              y=pMe->PosFind.ny;

              while(pMe->Cell[x][y].Father.nx!=NOVALUE)

              {

                  

                     m=pMe->Cell[x][y].Father.nx;

                     n=pMe->Cell[x][y].Father.ny;

                     pMe->Cell[x][y].CHILD[0].nx=m;

                     pMe->Cell[x][y].CHILD[0].ny=n;

                     pMe->Cell[x][y].nChild=1;

                     x=m;

                     y=n;

              }

       }

       else

       {

              while(pMe->Cell[x][y].Father.nx!=NOVALUE)

              {

           

                     m=pMe->Cell[x][y].Father.nx;

                     n=pMe->Cell[x][y].Father.ny;

                     pMe->Cell[x][y].CHILD[0].nx=m;

                     pMe->Cell[x][y].CHILD[0].ny=n;

                     pMe->Cell[x][y].nChild=1;

                     x=m;

                     y=n;

              }

       }

}

转载地址:http://bfedi.baihongyu.com/

你可能感兴趣的文章
C++11线程指南(8)--死锁
查看>>
算法与数据结构概述
查看>>
select, poll, epoll详解(一)
查看>>
select, poll, epoll详解(二)
查看>>
Swill使用感受
查看>>
C程序的内存分布
查看>>
C&C++(1) - extern “C“的作用
查看>>
C&C++(2) - void*在C和C++中的不同点
查看>>
C&C++(3) - 在C与C++中运行结果不同的程序
查看>>
C&C++(4) - C与C++中字符串的类型差异
查看>>
C++引用(1) - 基本介绍
查看>>
C++引用(2) - 引用能否指向一个无效地址?
查看>>
C++引用(3) - 使用引用或者指针传递参数
查看>>
C++函数重载(1) - 基本介绍
查看>>
C++函数重载(2) - 不能被重载的函数
查看>>
C++函数重载(3) - 函数重载中的const关键字
查看>>
C++函数重载(4) - 函数的返回类型
查看>>
C++函数重载(5) - 函数重载在类继承中的行为
查看>>
C++函数重载(6) - main函数重载
查看>>
C++内联函数
查看>>