一、实验目的
熟悉图的相关操作,掌握图的搜索算法及其应用,同时进一步练习栈与队列在实际问题中的应用。
二、问题描述
一只老鼠走进了一个迷宫,这个迷宫是由M行N列(如:10行8列)的方格构成的,相邻方格之间可能是相通的,也可能有墙相隔,各方格位置由其对应坐标确定,如图所示。迷宫在(1,1)处有一个入口,在(M,N)处有一个出口,在入口和出口之间有通路相通。问题是让你帮助老鼠找出从入口到出口的一条最短路径。
0 0 0 0 1 0 0 0
1 1 0 0 1 0 1 0
0 0 0 1 0 0 0 0
0 0 0 0 1 0 1 0
1 0 1 0 0 0 0 0
0 0 1 1 1 0 1 1
1 0 0 0 1 0 0 0
三、需求分析
迷宫用数组表示,1代表是墙走不通,0表示可以通行。边界可以扩充为墙,即M×N迷宫用(M+2)×(N+2)数组表示。目的是为老鼠找出从入口到出口一条最短路径。
采用图的广度优先搜索算法,新建空队列。最后运用递归从终点通过之前记录的父结点直到起始坐标并正向输出最短路径。
四、系统设计
坐标结构体:
struct poi
{
int x;
int y;
};
队列结构体:
struct qnode
{
poi data[maxsize];
int front;
int rear;
};
图的存储结构体:
struct node
{
int M;
int N;
int **G;
};
六个函数分别用于新建队列,队列数据插入,删除,新建图,广度遍历算法和递归输出最短路径。
首先新建队列和图结构,因为所有存储的最大值未知,所以都选择了定义头指针,在新建的时候动态存储数据。
将图进行广度遍历,标记已遍历坐标并存储坐标的上一个坐标。
最后从终点开始,通过寻找该坐标的上一个坐标进行遍历直到找到起始位置开始并倒序输出坐标。
五、调试分析
输入二维数组时,不能直接粘贴,需要有0隔开。
在图的遍历中需要注意溢出的问题和在对于图的存储定义的时候使用了0下标的位置所以在最后调试的时候修改了一些相关的判断语句。
六、代码实现
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
typedef struct qnode * Queue;
typedef struct node * Gragh;
struct poi **TreeFather;
int M,N;
struct poi
{
int x;
int y;
};
struct qnode
{
poi data[maxsize];
int front;
int rear;
};
struct node
{
int M;
int N;
int **G;
};
Queue Createqueue()
{
Queue Q=(Queue)malloc(sizeof(struct qnode));
Q->front=Q->rear=0;
return Q;
}
void Insertqueue(Queue Q,poi x)
{
if((Q->rear+1)%maxsize==Q->front)
printf("Full!");
else
{
Q->data[Q->rear]=x;
Q->rear=(Q->rear+1)%maxsize;
}
}
void Deletequeue(Queue Q,poi* temp)
{
if(Q->front==Q->rear)
return;
else
{
*temp=Q->data[Q->front];
Q->front=(Q->front+1)%maxsize;
}
}
Gragh Creategragh()
{
int i,j,v,e,k;
Gragh T=(Gragh)malloc(sizeof(struct node));
printf("请输入M和N:");
scanf("%d %d",&M,&N); //行数和列数
T->M=M;
T->N=N;
T->G=(int**)malloc(M*sizeof(int*));
TreeFather=(struct poi**)malloc(M*sizeof(struct poi*));
for(i=0;i<N;i++)
{
TreeFather[i]=(poi*)malloc(N*sizeof(poi));
T->G[i]=(int*)malloc(N*sizeof(int));
}
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
scanf("%d",&k);
T->G[i][j]=k;
}
}
return T;
}
void bfs(Gragh g,poi X,Queue Q)
{
int i,x,y;
poi temp,test;
Insertqueue(Q,X);
g->G[0][0]=2;
while(Q->front!=Q->rear)
{
Deletequeue(Q,&temp);
x=temp.x;
y=temp.y;
if(x<M-1&&g->G[x+1][y]==0&&x>=0)
{
g->G[x+1][y]=2;
test.x=x+1; test.y=y;
Insertqueue(Q,test);
TreeFather[x+1][y].x=x; TreeFather[x+1][y].y=y;
}
if(x>0&&g->G[x-1][y]==0&&x<=M-1)
{
g->G[x-1][y]=2;
test.x=x-1; test.y=y;
Insertqueue(Q,test);
TreeFather[x-1][y].x=x; TreeFather[x-1][y].y=y;
}
if(y<N-1&&g->G[x][y+1]==0&&y>=0)
{
g->G[x][y+1]=2;
test.x=x; test.y=y+1;
Insertqueue(Q,test);
TreeFather[x][y+1].x=x; TreeFather[x][y+1].y=y;
}
if(y>0&&g->G[x][y-1]==0&&y<=N-1)
{
g->G[x][y-1]=2;
test.x=x; test.y=y-1;
Insertqueue(Q,test);
TreeFather[x][y-1].x=x; TreeFather[x][y-1].y=y;
}
}
}
void search(int i,int j)
{
int x,y;
x=TreeFather[i][j].x;//父结点
y=TreeFather[i][j].y;
if(x>=0&&y>=0&&x+y>0)//出错点
{
search(x,y);
}
printf("->(%d,%d)",i+1,j+1);
}
int main()
{
int i,j;
poi temp;
temp.x=0; temp.y=0;
Queue Q=Createqueue();
Gragh gragh=Creategragh();
bfs(gragh,temp,Q);
printf("(1,1)");
search(M-1,N-1);
return 0;
}