围住神经猫,迷宫最短路径算法分析
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,另可索取源码
设图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,另可索取源码
相关文章推荐
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 算12/24点算法 布线问题/迷宫最短路径
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—SPFA(Shortest Path Faster Algorithm)算法分析与实现
- 最短路径算法的命令式、函数式版本对比分析
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 小算法系列-迷宫最短路径
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Floyd(弗洛伊德)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径分析算法in QGIS
- 【算法设计与分析】最短路径的算法
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—SPFA(Shortest Path Faster Algorithm)算法分析与实现(C/C++)