围住神经猫,迷宫最短路径算法分析

1、广度优先遍历的递归定义
     设图G的初态是所有顶点均未访问过。在G中任选一顶点v为源点,则广度优先遍历可以定义为:首先访问出发点v,接着依次访问v的所有邻接点w1,w2,…,wt,然后再依次访问与wl,w2,…,wt邻接的所有未曾访问过的顶点。依此类推,直至图中所有和源点v有路径相通的顶点都已访问到为止。此时从v开始的搜索过程结束。
     若G是连通图,则遍历完成;否则,在图C中另选一个尚未访问的顶点作为新源点继续上述的搜索过程,直至G中所有顶点均已被访问为止。
     广度优先遍历类似于树的按层次遍历。采用的搜索方法的特点是尽可能先对横向进行搜索,故称其为广度优先搜索(Breadth-FirstSearch)。相应的遍历也就自然地称为广度优先遍历。

2、广度优先搜索过程
     在广度优先搜索过程中,设x和y是两个相继要被访问的未访问过的顶点。它们的邻接点分别记为x1,x2,…,xs和y1,y2,…,yt
     为确保先访问的顶点其邻接点亦先被访问,在搜索过程中使用FIFO队列来保存已访问过的顶点。当访问x和y时,这两个顶点相继入队。此后,当x和y相继出队时,我们分别从x和y出发搜索其邻接点x1,x2,…,xs和y1,y2,…,yt,对其中未访者进行访问并将其人队。这种方法是将每个已访问的顶点人队,故保证了每个顶点至多只有一次人队。


//*******************************最短路径的简单应用***********************************************

围住神经猫,迷宫最短路径算法分析_第1张图片


源码:

//************************************************************************

//***作者  :                  czl

//***日期  :            2014/9/22

//***讨论qq群:    374894295   374894295374894295

//**********************************************************************
/************************************************************************/  
/* 图的邻接表存储结构                                                    */  
/************************************************************************/  
#include  
#define MaxVertexNum 91  
#define QueueSize 50   
bool visited[MaxVertexNum];
int parentnode[MaxVertexNum];
typedef int VertexType;  
typedef int EdgeType;  


typedef struct node     //边表结点  
{  
    int adjvex;         //邻接点域  
    struct node *next;  //域链  
    //若是要表示边上的权,则应增加一个数据域  
}EdgeNode;  
typedef struct vnode    //顶点边结点  
{  
    VertexType vertex;  //顶点域  
    EdgeNode *firstedge;//边表头指针  
}VertexNode;  
typedef VertexNode AdjList[MaxVertexNum];   //AdjList是邻接表类型  
typedef struct   
{  
    AdjList adjlist;    //邻接表  
    int n,e;            //图中当前顶点数和边数  
}ALGraph;               //对于简单的应用,无须定义此类型,可直接使用AdjList类型  


/************************************************************************/  
/* 插入新邻接结点 */  
/************************************************************************/  
void AddElem(int m_CatData[][9],ALGraph * &G,int phx,int phy,int i,int j)
{
EdgeNode * s;
if(!(((phx>=0&&(phx<=MAXX-1)&&phy>=0&&(phy<=MAXY-1)==TRUE))?false:true))
{//如果未越界
if(!m_CatData[phx][phy])
{
s=new EdgeNode; // 生成新边表结点s
s->adjvex=phx*MAXX+phy; // 邻接点序号为j     
s->next=G->adjlist[i*MAXX+j].firstedge; // 将新边表结点s插入到顶点Vi的边表头部     
G->adjlist[i*MAXX+j].firstedge=s;     
}
}
}


/************************************************************************/  
/* 建立无向图的邻接表算法                                               */  
/************************************************************************/  
void CreateGraphAL (ALGraph *G,int m_CatData[9][9])     
{     
EdgeNode * s;
//需要建图的x,y二维数组坐标
int phx=0;
int phy=0;
for (int i=0;i {
for (int j=0;j {
if (0==m_CatData[i][j])
{
G->adjlist[i*MAXX+j].vertex=i*MAXX+j;
   G->adjlist[i*MAXX+j].firstedge=NULL;
G->n++;
//1.判断当前位置位于奇数行还是偶数行
if ( i%2==0 )
{//如果是奇数行
//左上元素
phx=i-1;
phy=j-1;
AddElem(m_CatData,G,phx,phy,i,j);
//右上元素
phx=i-1;
phy=j;
AddElem(m_CatData,G,phx,phy,i,j);
//右边元素
phx=i;
phy=j+1;
AddElem(m_CatData,G,phx,phy,i,j);
//右下元素
phx=i+1;
phy=j;
AddElem(m_CatData,G,phx,phy,i,j);
//左下元素
phx=i+1;
phy=j-1;
AddElem(m_CatData,G,phx,phy,i,j);
//左边元素
phx=i;
phy=j-1;
AddElem(m_CatData,G,phx,phy,i,j);
}
else
{//如果是偶数行
//左上元素
phx=i-1;
phy=j;
AddElem(m_CatData,G,phx,phy,i,j);
//右上元素
phx=i-1;
phy=j+1;
AddElem(m_CatData,G,phx,phy,i,j);
//右边元素
phx=i;
phy=j+1;
AddElem(m_CatData,G,phx,phy,i,j);
//右下元素
phx=i+1;
phy=j+1;
AddElem(m_CatData,G,phx,phy,i,j);
//左下元素
phx=i+1;
phy=j;
AddElem(m_CatData,G,phx,phy,i,j);
//左边元素
phx=i;
phy=j-1;
AddElem(m_CatData,G,phx,phy,i,j);
}
}
else
{
G->adjlist[i*MAXX+j].vertex=-1;
G->adjlist[i*MAXX+j].firstedge=NULL;
}
}
}
}
/************************************************************************/  
/* 广度优先遍历                                                         */  
/************************************************************************/  
typedef struct    
{     
    int front;     
    int rear;     
    int count;     
    int data[QueueSize];     
}CirQueue;//循环队列的数据结构定义     
void InitQueue(CirQueue *Q)     
{//初始化队列     
    Q->front=Q->rear=0;     
    Q->count=0;     
}     
int QueueEmpty(CirQueue *Q)     
{//如果个数为0则队列空
    return Q->count==0;     
}     
int QueueFull(CirQueue *Q)     
{//判断队列为满     
    return Q->count==QueueSize;     
}     
void EnQueue(CirQueue *Q,int x)     
{//入队      
    if (QueueFull(Q))
{
//队列满
        printf("Queue overflow");     
}
    else    
    {      
        Q->count++;     
        Q->data[Q->rear]=x;     
        Q->rear=(Q->rear+1)%QueueSize;     
    }     
}     
int DeQueue(CirQueue *Q)     
{//出队     
    int temp;     
    if(QueueEmpty(Q))     
    {      
        printf("Queue underflow");     
        return NULL;     
    }     
    else    
    {     
        temp=Q->data[Q->front];     
        Q->count--;     
        Q->front=(Q->front+1)%QueueSize;     
        return temp;     
    }     
}     

//返回下一步要走的路径
int BFS(ALGraph*G,int k)  
{   // 以vk为源点对用邻接表表示的图G进行广度优先搜索  
    int i;  
    CirQueue Q;             //须将队列定义中DataType改为int  
    EdgeNode *p;  
    InitQueue(&Q);          //队列初始化
for (int i = 0 ; i {
parentnode[i]=-1;
}
    visited[k]=TRUE;   
    EnQueue(&Q,k);          //vk已访问,将其人队。(实际上是将其序号人队)
//是否是最短路径
bool isshstpath = false;
int  sonnode = -1;
CString str11;
    while(!QueueEmpty(&Q))  
    {                                   //队非空则执行  
        i=DeQueue(&Q);                  //相当于vi出队 
CString str;
str.Format(_T(" %d"),i);
str11+=str;

        p=G->adjlist[i].firstedge;       //取vi的边表头指针  
        while(p)  
        {                               //依次搜索vi的邻接点vj(令p->adjvex=j)  
            if(!visited[p->adjvex])     //若vj未访问过
            {                           
parentnode[p->adjvex]=G->adjlist[i].vertex;
                visited[p->adjvex]=TRUE;
CString str;
str.Format(_T(" %d"),p->adjvex);
str11+=str;
/*int tmpx = p->adjvex/MAXX;
int tmpy = ;*/
int tmpx=p->adjvex/MAXX;
int tmpy=p->adjvex-tmpx*MAXX;
if (false==isshstpath&&(tmpx==0||
tmpy==0||
tmpx==MAXX-1||
tmpy==MAXY-1))
{
sonnode=p->adjvex;
isshstpath=true;
break;
}
    
                EnQueue(&Q,p->adjvex);   //访问过的vj人队  
            }  
p=p->next;
             //找vi的下一邻接点  
        }


//找到最短路径则退出
if (isshstpath)
{
break;
}
    }  
if (isshstpath)
{
//最短路径是
while ( parentnode[sonnode]!=k )
{
sonnode=parentnode[sonnode];
}
return sonnode;
}
else
{
return -1;
}

}  

int BFSTraverseM(ALGraph *G,int catpos)     
{     
    int i;     
    for (i=0;i         visited[i]=FALSE; 
return BFS(G,catpos);

}


使用方法:

第一步:CreateGraphAL()函数创建图 

第二步:BFSTraverseM()广度优先遍历图搜索最短路径,并可以得到最短路径


注意:如有疑问可以加群374894295,另可索取源码

你可能感兴趣的:(围住神经猫,迷宫最短路径算法分析)