顺序栈的实现.docx
《顺序栈的实现.docx》由会员分享,可在线阅读,更多相关《顺序栈的实现.docx(15页珍藏版)》请在冰豆网上搜索。
![顺序栈的实现.docx](https://file1.bdocx.com/fileroot1/2023-6/7/26aa8a15-6bcf-4684-a602-fc3d7e6fea0a/26aa8a15-6bcf-4684-a602-fc3d7e6fea0a1.gif)
顺序栈的实现
数据结构课程实验报告
课程名称
数据结构
班级
计算123
实验日期
2014.05.15-2014.05.28
学号
实验成绩
实验名称
实验二顺序栈的实现
实
验
目
的
及
要
求
【实验目的】加深理解顺序栈的意义,理解用它的插入与删除操作的算法。
【实验要求】
首先实现一个以顺序存储结构(也可以是链式存储结构)的栈类型,然后编写一求解迷宫的非递归程序。
求得的通路以三元组(i,j,d)的形式输出,其中:
(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。
(理解InitStack、StackEmpty、Push、Pop和conversion等算法。
)
实验题目:
迷宫求解
实
验
环
境
硬件平台:
普通的PC机
软件平台:
Windows7操作系统
编程环境:
VisualC++6.0
实
验
容
【实验容】
用数制的转换算法调试顺序栈的基本操作算法。
编写主程序调用数制的转换conversion算法,再由conversion调用InitStack、StackEmpty、Push、Pop算法。
用不同的数转换成不同的进制调试程序并对相应的输出作出分析;修改输入数据,预期输出并验证输出的结果,加深对Push和Pop算法的理解。
【问题描述】
以一个m*n的二维矩阵表示迷宫,0和1分别表示迷宫中的通路和障碍。
设计一个程序,对任意设定的迷宫,求出一条(或所有)从入口到出口的通道,或得出没有通路的结论。
算
法
描
述
及
实
验
步
骤
实验设计:
抽象数据类型:
typedefstruct
{
intx;//当前位置的横坐标
inty;//当前位置的纵坐标
chartype;//当前位置的属性:
墙壁或通道(0/1)
boolisfoot;//判断当位置是否已走过,true代表已走过
}Position;//当前位置信息
typedefstruct
{
intorder;//脚步在地图上的序号
Positionseat;//行走的当前位置
intaspect;//下一步的方向
}Block;//脚步
typedefstruct
{
intwidth;//地图的长度
intheight;//地图的宽度
Position*site;//地图的各个位置
}Maze;//地图
typedefstruct
{
Block*base;
Block*top;
intlength;
intstacksize;
}Stack;
主程序模块:
intmain(intargc,_TCHAR*argv[])
{
Positionstart,end;
Blockblk;
StackS;
intwidth,height;
printf("输入迷宫比例X*Y\n");
printf("输入X:
");
scanf("%d",&width);
printf("输入Y:
");
scanf("%d",&height);
Maze*maze=GreatMaze(width,height);
PrintMaze(maze);
printf("\n");
printf("请输入入口坐标X:
");
scanf("%d",&start.x);
printf("请输入入口坐标Y:
");
scanf("%d",&start.y);
printf("请输入出后坐标X:
");
scanf("%d",&end.x);
printf("请输入出口坐标Y:
");
scanf("%d",&end.y);
MazePath(maze,start,end,S);
printf("走完所需路径长度为:
%d",S.length);
printf("\n");
StackSa;
InitStack(Sa);
while(S.length!
=0)
{
Pop(S,blk);
Push(Sa,blk);
}
while(Sa.length!
=0)
{
Pop(Sa,blk);
if(Sa.length!
=0)
printf("[%d,%d]->",blk.seat.x,blk.seat.y);//打印足迹
else
printf("[%d,%d]",blk.seat.x,blk.seat.y);//打印最后一步
}
}
各子程序函数:
Maze*GreatMaze(intwidth,intheight)//创建地图
voidPrintMaze(Maze*maze)//打印地图
intPositionComparison(Positionmaze,Positionpos)//判断当前位置是否合法
intPass(Maze*maze,Positioncurpos)//判断当前位置是否可以前进或者是否走过
voidFootSet(Maze*maze,Positionsite)//留下足迹
PositionNextPos(Position&cur,intaspect)//判断方向
IntMazePath(Maze*maze,Positionstart,Positionend,Stack&S)//搜索从入口到出口的路径
迷宫求解流程图:
路径搜索算法:
Do{
若当前位置可通,
则{
将当前位置插入栈顶; //纳入通路
若该位置是出口位置,则结束; //求得路径存放在栈中
否则切换当前位置的东邻方块为新的当前位置;
}
否则,
若栈不空切栈顶位置尚有其他方向未经探索,
则设定新的当前位置为沿顺时针方向旋转找到的栈顶位置的下一相邻块;
若栈不空但栈顶位置的四周均不可通;
则{
删去栈顶位置; //从路径中删除该通道块
若栈不空,则重新测试新的栈顶位置,
直至找到一个可通的相邻块或出栈至栈空
调
试
过
程
及
实
验
结
果
总
结
在这次实验中遇到了很多实际性的问题,在实验设计中才发现,书本上理论性的东西与在实际运用中的还是有一定的出入的,所以有些问题不但要深入地理解,而且要不断地更正以前的错误思维,才能完成实验设计。
通过这次实验设计我也发现了自身存在的不足之处,虽然感觉理论上已经掌握,但在运用到实践的过程中仍有意想不到的困惑,经过一番努力才得以解决。
实验中,通过自己不断的学习,以及和同学们之间的讨论,让我进一步的了解了栈与数组的应用,这次实验使我受益匪浅。
附
录
#include"stdlib.h"
#include"stdio.h"
#include"time.h"
#include
#defineSTACK_INIT_SIZE10
typedefstruct
{
intx;//当前位置的横坐标
inty;//当前位置的纵坐标
chartype;//当前位置的属性:
墙壁或通道(0/1)
intisfoot;//判断当位置是否已走过,true代表已走过
}Position;//当前位置信息
typedefstruct
{
intorder;//脚步在地图上的序号
Positionseat;//行走的当前位置
intaspect;//下一步的方向
}Block;//脚步
typedefstruct
{
intwidth;//地图的长度
intheight;//地图的宽度
Position*site;//地图的各个位置
}Maze;//地图
typedefstruct
{
Block*base;
Block*top;
intlength;
intstacksize;
}Stack;
intInitStack(Stack&S)
{
S.base=(Block*)malloc(STACK_INIT_SIZE*sizeof(Block));
if(!
S.base)return0;
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
S.length=0;
return1;
}
intPush(Stack&S,Blockdata)
{
if(S.length>=S.stacksize)
{
S.base=(Block*)realloc(S.base,(STACK_INIT_SIZE+S.stacksize)*sizeof(Block));
if(!
S.base)return0;
S.top=S.base+S.stacksize;
S.stacksize+=STACK_INIT_SIZE;
}
*S.top=data;
S.top++;
S.length++;
return1;
}
intPop(Stack&S,Block&data)
{
if(S.top==S.base)return0;
S.top--;
data=*S.top;
S.length--;
return1;
}
voidDestroyStack(Stack&S)
{
free(S.base);
}
voidClearStack(Stack&S)
{
DestroyStack(S);
InitStack(S);
}
Maze*GreatMaze(intwidth,intheight)//创建地图
{
Maze*maze=(Maze*)malloc(sizeof(Maze));//为地图分配存放空间
maze->width=width;
maze->height=height;
maze->site=(Position*)malloc(width*height*sizeof(Position));//为地图坐标分配空间
srand((unsigned)time(NULL));//产生随机数
inti,k,j=0;
if(width>0&&height>0)
{
for(i=0;iwidth;i++)
for(k=0;jheight*(i+1);j++,k++)
{
maze->site[j].x=k;
maze->site[j].y=i;
intn=rand()%9+1;
if(n>5)
maze->site[j].type='0';//设置墙壁
else
maze->site[j].type='1';//设置通道
}
}
returnmaze;//返回定义好的地图
}
voidPrintMaze(Maze*maze)//打印地图
{
inti,j=0;
printf("\t");
for(i=0;iwidth;i++)
printf("%d",i);//打印横坐标
printf("\n");
printf("\n");
for(i=0;iheight;i++)
{
printf("%d\t",i);//打印纵坐标
for(j;jwidth*(i+1);j++)
if(maze->site[j].type=='0')
printf("■");//打印墙壁
else
printf("□");//打印通道
printf("\n");
}
}
intPositionComparison(Positionmaze,Positionpos)//判断当前位置是否合法
{
if(maze.x==pos.x&&maze.y==pos.y)
return1;
else
return0;
}
intPass(Maze*maze,Positioncurpos)
{
Position*pos;
pos=maze->site;
for(inti=0;iheight*maze->width;i++)
{
if(PositionComparison(*pos,curpos))//判断当前位置是否合法
if(pos->type=='0'||maze->site[i].isfoot==true)//判断当前位置是否可以前进或者是否走过
return0;
else
return1;
pos++;
}
return0;
}
voidFootSet(Maze*maze,Positionsite)//留下足迹
{
for(inti=0;iheight*maze->width;i++)
{
if(PositionComparison(maze->site[i],site))
{
maze->site[i].isfoot=true;//留下已走过的足迹
}
}
}
PositionNextPos(Position&cur,intaspect)
{
switch(aspect)
{
case1:
cur.y+=1;break;//向下
case2:
cur.x+=1;break;//向右
case3:
cur.y-=1;break;//向上
case4:
cur.x-=1;break;//向左
}
returncur;
}
intMazePath(Maze*maze,Positionstart,Positionend,Stack&S)
{
intcurstep;
Positioncurpos;//探索的位置
Blockpath;//脚步
InitStack(S);
curpos.x=start.x;
curpos.y=start.y;//入口
curstep=1;//探索第一步
do
{
if(Pass(maze,curpos))//当前位置是否可以通过
{
FootSet(maze,curpos);//留下足迹
path.order=curstep;//当前走过的总步数
path.seat=curpos;//踏下脚步
path.aspect=1;
Push(S,path);//保存脚步
if(PositionComparison(curpos,end))//判断是否是重点
return1;
curpos=NextPos(curpos,1);//继续向下一个方向探索
curstep++;//探索的步数增加一
}
else
{
if(S.length!
=0)
{
Pop(S,path);//退到上一步
while(path.aspect==4&&S.length!
=0)//如果当前位置无法再前行,再退回一步
Pop(S,path);
if(path.aspect<4)//如果当前位置可再继续探索
{
path.aspect++;//转变探索方向
Push(S,path);//保存当前位置(只更新了探索方向)
curpos=NextPos(path.seat,path.aspect);//继续探索下一个方向
}
}
}
}while(S.length!
=0);
return0;
}
intmain(intargc,_TCHAR*argv[])
{
Positionstart,end;
Blockblk;
StackS;
intwidth,height;
printf("输入迷宫比例X*Y\n");
printf("输入X:
");
scanf("%d",&width);
printf("输入Y:
");
scanf("%d",&height);
Maze*maze=GreatMaze(width,height);
PrintMaze(maze);
printf("\n");
printf("请输入入口坐标X:
");
scanf("%d",&start.x);
printf("请输入入口坐标Y:
");
scanf("%d",&start.y);
printf("请输入出后坐标X:
");
scanf("%d",&end.x);
printf("请输入出口坐标Y:
");
scanf("%d",&end.y);
MazePath(maze,start,end,S);
printf("走完所需路径长度为:
%d",S.length);
printf("\n");
StackSa;
InitStack(Sa);
while(S.length!
=0)
{
Pop(S,blk);
Push(Sa,blk);
}
while(Sa.length!
=0)
{
Pop(Sa,blk);
if(Sa.length!
=0)
printf("[%d,%d]->",blk.seat.x,blk.seat.y);//打印足迹
else
printf("[%d,%d]",blk.seat.x,blk.seat.y);//打印最后一步
}
}