队列的应用迷宫问题实验样本.docx
《队列的应用迷宫问题实验样本.docx》由会员分享,可在线阅读,更多相关《队列的应用迷宫问题实验样本.docx(14页珍藏版)》请在冰豆网上搜索。
队列的应用迷宫问题实验样本
南昌航空大学实验报告
二O年月日
课程名称:
数据结构实验名称:
实验四:
队列的应用
班级:
12203125学生姓名:
李平同组人:
指导教师评定:
签名:
题目:
假设迷宫由m行n列构成,有一个入口和一个出口,入口坐标为(1,1),出口坐标为(m,n),试找出一条从入口通往出口的最短路径。
设计算法并编程输出一条通过迷宫的最短路径或报告一个“无法通过”的信息。
要求:
用栈和队列实现,不允许使用递归算法。
一、需求分析
⒈用栈的基本操作完成迷宫问题的求解,其中栈的基本操作作为一个独立的模块存在。
⒉以二维数组b[m][n]表示迷宫,b[i][j]表示迷宫中相应(i,j)位置的通行状态(0:
表示可以通行,1:
表示有墙,不可通行),完成迷宫的抽象数据类型,包括出口、入口位置等。
⒊程序中完成对应迷宫的初始化。
⒋迷宫的入口位置和出口位置在合法范围内由用户而定。
⒌程序完成对迷宫路径的搜索,如果存在路径,则输出走出迷宫的路径。
⒍程序执行的命令:
⑴创建初始化迷宫;
⑵搜索迷宫;
⑶输出搜索结果。
二、概要设计
⒈设计栈的抽象数据类型定义:
ADTStack{
数据对象:
D={ai:
|ai∈PositionSet,i=1…n,n≥0}
数据关系:
R1={|ai-1,ai∈d,i=2,…n}
基本操作:
操作结果
InitStack(&S)构造一个空栈,完成栈的初始化S
DestoryStack(&S)撤消一个已经存在的栈S
ClearStack(&S)将栈S重新置空
StackLength(S)返回栈的长度
GetTop(S,&e)用e返回栈S的栈顶元素
StackEmpty(S)若S为空返回1,否则返回0
Push(&S,e)将新的元素e压入栈顶
Pop(&S,e)删除栈顶元素,并用e返回其值
StackTraverse(s)将栈S的所有元素输出
}ADTStack;
⒉迷宫的抽象数据类型定义:
ADTMaze{
数据对象:
D:
={aij,Start,end|aij,Start,end∈{}0≤i≤m+2,0≤j≤n+2,m,n≥0}
数据关系:
R={ROW.COL}
Row={|ai-1,aij∈Di=1,…,m+2,j=1,…,n+2}
Col={|aijaij-1∈D}
基本操作:
SetMaze(&Maze)
初始条件:
Maze已经定义,Maze的下属单元二维数组Maze.M[row+2][d+2]已存在,Maze.start,Maze.end也已作为下属存储单元存在
操作结果:
构成数据迷宫,用数值标识迷宫的物理状态,以0表示通路,以1表示障碍,由终端读取迷宫空间大小,各点处的具体物理状态及Start和End点位置,完成迷宫构建
Pass(&Mazem,&Nposition,Position,di)
初始条件:
已知目前迷宫状态及当前位置、下一步探索方向di
操作结果:
完成相应的搜索任务,如果可行,则用Nposition返回下一步位置,并将Maze状态改变为相应点已走过情况
PrintMaze(Maze)
操作结果:
输出字符标示的迷宫
FindWay(Maze,&way)
操作结果:
利用Pass搜索迷宫,用way返回搜索所得路径。
如不存在,返回0
PrintWay(Maze,way)
操作结果:
将Maze及相应最短路径一起打印输出
}ADTMAZE,
⒊本程序模块结构
⑴主函数模块
voidmain(){
初始化;
do{
接受命令;
处理命令;
}while(退出命令)
}
⑵栈模块——实现栈抽象数据类型;
⑶迷宫模块——实现迷宫抽象数据类型;
各模块之间的调用关系如下:
主程序模块
迷宫模块
栈模块
三、详细设计
⒈基本数据类型操作
⑴栈模块
①structsqstack{
int*base;//在栈初始化之前和销毁之后为NULL
int*top;//栈顶指针,在栈顶元素上方一单元处
intstacksize;//当前已分配存储空间,以元素为单位
};//线性存储结构
②参数设置:
#defineSTACK_INIT_SIZE20;
#defineSTACKINIREMENT10;
//----------基本操作的算法描述--------------------
//建一个空栈
voidinitstack(sqstack&s){
s.base=(int*)malloc(SIZE*sizeof(int));
if(!
s.base){printf("\n内存不足\n");exit(0);}
s.top=s.base;
s.stacksize=SIZE;
}
//出栈
intpop(sqstack&s,int*e){
if(s.top==s.base)return0;
*e=*(--s.top);
return1;
}
//进栈
voidpush(sqstack&s,inte){
if(s.top-s.base>=s.stacksize){
s.base=(int*)realloc(s.base,
(s.stacksize+INCR)*sizeof(int));
if(!
s.base)exit(0);
s.top=s.base+s.stacksize;
s.stacksize+=INCR;
}
*(s.top)=e;
(s.top)++;
}
//得到栈的第一个元素
intgettop(sqstack&s,int*e){
if(s.top==s.base)return0;
*e=*(s.top-1);
return1;
}⑵迷宫模块:
①迷宫的数据类型
//迷宫信息的结构体数组
structmigong{
intflag;
intdir;
};
//建一迷宫数组,用于存放迷宫数据
structmigonga[10][10];
②迷宫模块中的基本操作
//求解迷宫
intmasepath(inti,intj,intm,intn,sqstack&s){
if(a[i][j].flag==1){printf("\n入口错误\n");return0;}
do{
if(i==m&&j==n){push(s,i);push(s,j);return1;}
else{
if(a[i][j].dir==1){
if(a[i][j+1].flag==1)a[i][j].dir++;
else{
push(s,i);push(s,j);a[i][j].flag=1;j++;continue;
}
}
if(a[i][j].dir==2){
if(a[i+1][j].flag==1)a[i][j].dir++;
else{
push(s,i);push(s,j);a[i][j].flag=1;i++;continue;
}
}
if(a[i][j].dir==3){
if(a[i][j-1].flag==1)a[i][j].dir++;
else{
push(s,i);push(s,j);a[i][j].flag=1;j--;continue;
}
}
if(a[i][j].dir==4){
if(a[i-1][j].flag==1)a[i][j].dir++;
else{
push(s,i);push(s,j);a[i][j].flag=1;i--;continue;
}
}
else{
a[i][j].flag=1;
pop(s,&j);pop(s,&i);
a[i][j].flag=0;
}
}
}
while(s.top!
=s.base);
printf("\n没有出路\n");
return2;
}⑶主函数算法:
voidmain(){
intm,n,x,y,i,j,r=1;
sqstacks1,s2;
initstack(s2);
initstack(s1);
intb[10][10]={
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,1,1,0,0,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1},
};
//输出迷宫
printf("所建迷宫如下图,其中1表示墙,0表示通路\n");
printf("0123456789\n\n");
for(i=0;i<10;i++){
printf("%d",i);
for(j=0;j<10;j++){
a[i][j].flag=b[i][j];
printf("%d",b[i][j]);
a[i][j].dir=1;
}
printf("\n");
}
//调用迷宫程序
printf("请输入出口位置\n");
scanf("%d",&m);
scanf("%d",&n);
masepath(1,1,m,n,s1);
while(s1.top!
=s1.base){
pop(s1,&x);
push(s2,x);
}
//输出路径
printf("\n走出迷宫的路径为:
\n");
while(s2.top!
=s2.base){
pop(s2,&x);pop(s2,&y);
printf("<%d,%d>",x,y);
if(r++%5==0)
printf("\n");
}
}
⒉函数的调用关系反映了本演示程序的层次结构
main
InitStackDestoryStackFindWayPrintWayPrintmigongPassSetmigong
……
PushGetTopPopStackLengthStackEmptyClearStack
四、调试分析
⒈初始化迷宫采用的是用二维数组b[][]来初始化,一开始就自己定义了一个迷宫,省去了运行时输入。
⒉用“1”“0”来表示迷宫的障碍和通路比较适合用户观察,便于操作。
⒊对于栈要注意指针的使用和带入带回“&”的使用。
五、用户手册
⒈本程序的运行环境为DOS操作系统,执行文件为migong.exe;
⒉进入演示程序后,即显示对话形式的提示操作过程,
如:
请输入出口位置
3.按enter开始后,程序自动进行对所建迷宫的搜索,并将搜索结果;
⒍进行下一个迷宫处理单元或退出程序。
六、测试数据
七、附录
⒈源程序文件清单:
栈:
stack.c
迷宫:
migong.c
⒉源程序
#include
#include
#include
#defineSIZE100
#defineINCR20
//迷宫信息的结构体数组
structmigong{
intflag;
intdir;
};
//建一迷宫数组,用于存放迷宫数据
structmigonga[10][10];
//栈类型,用于存放走过的路径
structsqstack{
int*base;
int*top;
intstacksize;
};
//建一个空栈
voidinitstack(sqstack&s){
s.base=(int*)malloc(SIZE*sizeof(int));
if(!
s.base){printf("\n内存不足\n");exit(0);}
s.top=s.base;
s.stacksize=SIZE;
}
//出栈
intpop(sqstack&s,int*e){
if(s.top==s.base)return0;
*e=*(--s.top);
return1;
}
//进栈
voidpush(sqstack&s,inte){
if(s.top-s.base>=s.stacksize){
s.base=(int*)realloc(s.base,
(s.stacksize+INCR)*sizeof(int));
if(!
s.base)exit(0);
s.top=s.base+s.stacksize;
s.stacksize+=INCR;
}
*(s.top)=e;
(s.top)++;
}
//得到栈的第一个元素
intgettop(sqstack&s,int*e){
if(s.top==s.base)return0;
*e=*(s.top-1);
return1;
}
//求解迷宫
intmasepath(inti,intj,intm,intn,sqstack&s){
if(a[i][j].flag==1){printf("\n入口错误\n");return0;}
do{
if(i==m&&j==n){push(s,i);push(s,j);return1;}
else{
if(a[i][j].dir==1){
if(a[i][j+1].flag==1)a[i][j].dir++;
else{
push(s,i);push(s,j);a[i][j].flag=1;j++;continue;
}
}
if(a[i][j].dir==2){
if(a[i+1][j].flag==1)a[i][j].dir++;
else{
push(s,i);push(s,j);a[i][j].flag=1;i++;continue;
}
}
if(a[i][j].dir==3){
if(a[i][j-1].flag==1)a[i][j].dir++;
else{
push(s,i);push(s,j);a[i][j].flag=1;j--;continue;
}
}
if(a[i][j].dir==4){
if(a[i-1][j].flag==1)a[i][j].dir++;
else{
push(s,i);push(s,j);a[i][j].flag=1;i--;continue;
}
}
else{
a[i][j].flag=1;
pop(s,&j);pop(s,&i);
a[i][j].flag=0;
}
}
}
while(s.top!
=s.base);
printf("\n没有出路\n");
return2;
}
voidmain(){
intm,n,x,y,i,j,r=1;
sqstacks1,s2;
initstack(s2);
initstack(s1);
intb[10][10]={
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,1,1,0,0,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1},
};
//输出迷宫
printf("所建迷宫如下图,其中1表示墙,0表示通路\n");
printf("0123456789\n\n");
for(i=0;i<10;i++){
printf("%d",i);
for(j=0;j<10;j++){
a[i][j].flag=b[i][j];
printf("%d",b[i][j]);
a[i][j].dir=1;
}
printf("\n");
}
//调用迷宫程序
printf("请输入出口位置\n");
scanf("%d",&m);
scanf("%d",&n);
masepath(1,1,m,n,s1);
while(s1.top!
=s1.base){
pop(s1,&x);
push(s2,x);
}
//输出路径
printf("\n走出迷宫的路径为:
\n");
while(s2.top!
=s2.base){
pop(s2,&x);pop(s2,&y);
printf("<%d,%d>",x,y);
if(r++%5==0)
printf("\n");
}
}