基于栈的C语言迷宫问题与实现一.问题描述多年以来,迷宫问题一直是令人感兴趣的题目。实验心理学家训练老鼠在迷宫中寻找食物。许多神秘主义小说家也曾经把英国乡村花园迷宫作为谋杀现场。于是,老鼠过迷宫问题就此产生,这是一个很有趣的计算机问题,主要利用“栈”是老鼠通过尝试的办法从入口穿过迷宫走到出口。迷宫只有两个门,一个叫做入口,另一个叫做出口。把一只老鼠从一个无顶盖的大盒子的入口处赶进迷宫。迷宫中设置很多隔壁,对前进方向形成了多处障碍,在迷宫的唯一出口处放置了一块奶酪,吸引老鼠在迷宫中寻找通路以到达出口。求解迷宫问题,即找出从入口到出口的路径。一个迷宫可用上图所示方阵[m,n]表示,0表示能通过,1表示不能通过。现假设耗子从左上角[1,1]进入迷宫,编写算法,寻求一条从右下角[m,n]出去的路径。下图是一个迷宫的示意图:入口出口迷宫示意图二.算法基本思想迷宫问题是栈应用的一个典型例子。求解过程可采用回溯法。回溯法是一种不断试探且及时纠正错误的搜索方法。从入口出发,按某一方向向前探索,若能走通(未走过的),即某处可以到达,则到达新点,否则试探下一方向;若所有的方向均没有通路,则沿原路返回前一点,换下一个方向再继续试探,直到所有可能的通路都探索到,或找到一条通路,或无路可走又返回到入口点。在求解过程中,为了保证在到达某一点后不能向前继续行走(无路)时,能正确返回前一点以便继续从下一个方向向前试探,则需要用一个栈保存所能够到达的每一点的下标及从该点前进的方向,栈中保存的就是一条迷宫的通路。为了确保程序能够终止,调整时,必须保证曾被放弃过的填数序列不被再次试验,即要求按某种有序模型生成填数序列。给解的候选者设定一个被检验的顺序,按这个顺序逐一生成候选者并检验。三.主要数据结构1.方阵栈:#defineSTACK_INI_SIZE100typedefstruct{int*top;//指向栈的顶端域int*base;//指向栈的低端域intlength;//栈的长度intstacksize;//栈的最大长度}sqstack;2.产生迷宫的矩阵二维数组为了使每一个迷宫存在迷宫的边界和两个端口:入口、出口,设置了一个二维数组,在迷宫的周边定义为1,使得迷宫存在边界,并在(1,1),(x-2,y-2)初定义为0,即定义迷宫的出口,大大减小了无解的情况。for(i=0;ix;i++)for(j=0;jy;j++)mg[i][j]=rand()%3;//产生随机数i=0;for(j=0;jy;j++){mg[i][j]=1;//定义边界mg[j][i]=1;}i=y-1;for(j=0;jx;j++)//定义边界mg[j][i]=1;i=x-1;for(j=0;jy;j++)mg[i][j]=1;mg[1][1]=0;//定义出口和入口mg[x-2][y-2]=0;四.主要函数功能1.voidinitstack(sqstack*s);/*初始化栈*/将栈顶和栈底分别申请一段动态存储空间,将栈分配长度为100的空间,将栈的原始长度定义为22.voidstackpush(sqstack*s,int);/*增加栈顶*/将栈的动态存储空间增加50,将栈顶指针上移相应高度,特殊情况单独考虑见程序。3.voidstackpop(sqstack*s);/*撤销栈顶*/栈空提示无法删除,其他情况删除栈顶。4.voidstackinput(sqstack*s);/*输出栈*/输出寻找到的一条迷宫路径5.intmgway(sqstack*s);/*迷宫路径*/寻找到可执行的一条迷宫路径6.voiddestorystack(sqstack*s);/*撤销栈S*/将栈内元素清空7.voidmakemg(sqstack*s);/*制造迷宫*/输入迷宫的长宽(2-15),并产生迷宫图五.算例(生成演算结果)本程序的运算环境为:codeblocks输入界面:输入错误则重新输入5*5的迷宫图及其路径:继续输入错误提示:重新输入结果:可以看到每个迷宫都存在“围墙”六.分析算法1.空间复杂度固定空间需求:25*25的二维迷宫数组可变空间需求:初始化栈中申请了100倍int型所占空间大小的动态空间,加入栈顶时额外申请50倍int型所占空间大小2.时间复杂度可以通过“程序步”对程序的时间复杂度进行测量,可以引入count计数器进行测量,考虑到其复杂程度,本程序将不采用此方法。本程序的排错率较高,计算机会改掉没有通路的栈,并随机生成有通路迷宫,提高了程序的执行效率,并给迷宫添加了必要的围墙和出口、入口有助于执行效率的提高。但对于路径的搜索,栈并没有引入方向指针,在后面,通过flag进行标记来确定栈的路径的寻找的,一定程度上会影响执行效率。附录:C语言源程序#includestdio.h#includestdlib.h#defineSTACK_INI_SIZE100#defineSTACKINCREMENT50#defineNULL0typedefstruct{int*top;int*base;intlength;intstacksize;}sqstack;intmg[25][25];intm=1,n=1,x,y;/*********************************************/main(){voidinitstack(sqstack*s);/*初始化栈*/voidstackpush(sqstack*s,int);/*增加栈顶*/voidstackpop(sqstack*s);/*撤销栈顶*/voidstackinput(sqstack*s);/*输出栈*/intmgway(sqstack*s);/*迷宫路径*/voiddestorystack(sqstack*s);/*撤销栈S*/voidmakemg(sqstack*s);/*制造迷宫*/sqstacks;inti,flag1=1,flag2=1,flag3=1;charch;srand((unsigned)time(NULL));while(flag1){initstack(&s);flag2=1;makemg(&s);i=mgway(&s);if(i==0)printf(此迷宫没有通路\n);elsestackinput(&s);destorystack(&s);printf(还继续么?);fflush(stdin);scanf(%c,&ch);while(flag2){if(ch=='n'||ch=='N'){flag1=0;flag2=0;}elseif(ch=='y'||ch=='Y'){flag1=1;flag2=0;}else{printf(输入错误请重新输入);fflush(stdin);scanf(%c,&ch);}}}}/*********************************************/voidinitstack(sqstack*s)/*初始化栈*/{s-top=s-base=(int*)malloc(STACK_INI_SIZE*sizeof(int));if(!s-base)exit(1);s-stacksize=STACK_INI_SIZE;*(s-base)=0;s-top++;*(s-top)=101;s-top++;s-length=2;}/*********************************************/voidstackpush(sqstack*s,inti)/*增加栈顶*/{if(s-length=s-stacksize){printf(路过);s-base=(int*)realloc(s-base,(STACK_INI_SIZE+STACKINCREMENT)*sizeof(int));if(!s-base)exit(1);s-top=s-base+s-length;s-stacksize+=STACKINCREMENT;stackinput(s);}if(s-length==0){*(s-base)=i;s-top++;s-length++;}else{*(s-top)=i;s-top++;s-length++;}}/*********************************************/voidstackpop(sqstack*s)/*删除栈顶*/{if(s-length==0)printf(栈空无法删除);if(s-length==1){s-top--;*(s-top)=*(s-base)=NULL;s-length=0;}else{s-top--;*(s-top)=NULL;s-length--;}}/*********************************************/voidstackinput(sqstack*s)/*迷宫栈的输出*/{intw,x,y,z,i=0,*p;p=s-base;p++;printf(迷宫正确路径\n);while(p!=s-top){printf((%d%d,%d%d),x=*p/1000,y=*p/100%10,z=*p%100/10,w=*p%10);p++;i++;if(i==7){printf(\n);i=0;}}}/*********************************************/intmgway(sqstack*s)/*迷宫路径*/{intgudge(sqstack*s,int);/*判断是否能通行*/inthoming(sqstack*s);/*退栈后I所对应的方向*/inti=1,j,k;while(s-top!=s-base){if(i5)j=gudge(s,i);if(j==1&&i5){k=m*100+n;stackpush(s,k);if(m==y-2&&n==x-2){return(1);}elsei=1;}else{if(m==0&&n==0)return(0);elseif(i==4||i==5){i=homing(s);stackpop(s);i++;}elsei++;}}return(0);}/*********************************************/intgudge(sqstack*s,inti)/*退栈后i所对应的方向*/{intecho(sqstack*s);if(i==1)n++;if(i==2)m++;if(i==3)n--;if(i==4)m--;if((mg[m][n]==0||mg[m][n]==2)&&echo(s))return(1);else{if(i==1)n--;if(i==2)m--;if(i==3)n++;if(i==4)m++;return(0);}}/*********************************************/intecho(sqstack*s){inti,*p,*q;i=m*100+n;p=s-top;q=s-base;q++;p--;while(p!=q&&*p!=i)p--;if(*p==i)return(0);elsereturn(1);}/*********************************************/inthoming(sqstack*s)/*i退位后所对应的方向*/{inta,b,c,d,*q;q=s-top;q--;a=(*q)/100;b=(*q)%100;q--;c=(*q)/100;d=(*q)%100;m=(*q)/100;n=(*q)%100;if(a==c){if(d-b==1)return(3);elseif(d-b==-1)return(1);}elseif(b==d){if(c-a==1)return(4)