您的位置:首页 > 其它

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

2014-09-24 13:19 501 查看
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,对其中未访者进行访问并将其人队。这种方法是将每个已访问的顶点人队,故保证了每个顶点至多只有一次人队。

<script src="https://code.csdn.net/snippets/474345.js"></script>

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



源码:

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

//***作者  :                  czl
//***日期  :            2014/9/22

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

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

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

/* 图的邻接表存储结构                                                    */  

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

#include <stdio.h>  

#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<MAXX;i++)
{
for (int j=0;j<MAXY;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<MaxVertexNum ; 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<MaxVertexNum;i++)     

        visited[i]=FALSE; 
return BFS(G,catpos);
}

使用方法:

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

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

注意:如有疑问可以加群374894295,另可索取源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: