当前位置:文档之家› 数据结构课程设计迷宫求解

数据结构课程设计迷宫求解

迷宫求解一.问题描述对迷宫问题的求解过程实际就是从入口开始,一步一步地走到出口的过程。

基本要求:输入一个任意大小的迷宫数据,用递归和非递归两种方法求出一条走出迷宫的路径,并将路径输出。

二.设计思路在本程序中用两种方法求解迷宫问题-非递归算法和递归算法。

对于非递归算法采用回溯的思想,即从入口出发,按某一方向向前探索,若能走通,并且未走过,则说明某处可以到达,即能到达新点,否则试探下一方向;若所有的方向均没有通路,或无路可走又返回到入口点。

在求解过程中,为了保证在到达某一点后不能向前继续行走(无路)时,能正确返回前一点以便继续从下一个方向向前试探,则需要用一个栈保存所能到达的没一点的下标及该点前进的方向,然后通过对各个点的进出栈操作来求得迷宫通路。

对于递归算法,在当前位置按照一定的策略寻找下个位置,在下个位置又按照相同的策略寻找下下个位置…;直到当前位置就是出口点,每一步的走法都是这样的。

随着一步一步的移动,求解的规模不断减小;如果起始位置是出口,说明路径找到,算法结束,如果起始位置的四个方向都走不通,说明迷宫没有路径,算法也结束。

另外,为了保证迷宫的每个点都有四个方向可以试探,简化求解过程,将迷宫四周的值全部设为1,因此将m行n列的迷宫扩建为m+2行,n+2列,同时用数组来保存迷宫阵列。

三.数据结构设计在迷宫阵列中每个点都有四个方向可以试探,假设当前点的坐标(x,y),与其相邻的四个点的坐标都可根据该点的相邻方位而得到,为了简化问题,方便求出新点的坐标,将从正东开始沿顺时针进行的这四个方向的坐标增量放在一个结构数组move[4]中,每个元素有两个域组成,其中x为横坐标增量,y为纵坐标增量,定义如下:typedef struct{int x,y;}item;为到达了某点而无路可走时需返回前一点,再从前一点开始向下一个方向继续试探。

因此,还要将从前一点到本点的方向压入栈中。

栈中的元素由行、列、方向组成,定义如下:typedef struct{int x,y,d;}DataType;由于在非递归算法求解迷宫的过程中用到栈,所以需定义栈的类型,本程序中用的是顺序栈,类型定义如下;typedef struct{DataType data[MAXSIZE];int top;}SeqStack, *PSeqStack;四.功能函数设计(1)函数PSeqStack Init_SeqStack()此函数实现对栈的初始化工作。

(2)函数Empty_SeqStack(PSeqStack S)此函数用于判断栈是否为空。

(3)函数Push_SeqStack (PSeqStack S, DataType x) 此函数实现入栈操作。

(4)函数Pop_SeqStack(PSeqStack S ,DataType *x)此函数实现出栈操作。

(5)函数Destory_Seqstack(PSeqStack *S)此函数执行栈的销毁操作,释放内存空间。

(6)函数mazepath(int maze[][n+2],item move[],int x0,int y0) 此函数实现对迷宫问题的非递归算法求解。

在求解过程中需调用上面定义的关于栈的一系列函数(栈的初始化,判空,入栈,出栈,栈的销毁),进而求得迷宫路径。

(7)函数path(int maze[][n+2],item move[],int x,int y,int step)此函数实现对迷宫问题的递归算法求解。

(8)函数print_way(int maze[][n+2],item move[])此函数用于在递归算法求解迷宫后输出求解后的结果,即打印迷宫路径。

(9)函数copy(int maze[][n+2],int ms[][n+2])此函数的作用是复制一下输入的原始迷宫序列,因为本程序是通过菜单选择求解迷宫的实现方式,将非递归算法和递归算法放在一起通过菜单选择实现,在调用完一种算法后,为保证调用另一种算法时原始迷宫序列未改变,所以需调用此函数来原始迷宫序列备份一下。

(10)主函数main()定义变量,实现迷宫的输入操作,通过菜单选择求解迷宫路径的实现方法,调用相关函数。

(11)系统功能总体模块(a)栈的初始化(b)判栈空函数(c)入栈(d)出栈(e)销毁栈(f)非递归算法求解迷宫函数(g)递归算法求解迷宫函数(h)打印递归算法求解迷宫的路径函数(i)复制原始迷宫阵列函数(j)主函数五.编码实现#include<stdio.h>#include<stdlib.h>#define m 6#define n 8#define MAXSIZE 100typedef struct{int x,y;}item;item move[4];typedef struct{int x,y,d;}DataType;typedef struct{DataType data[MAXSIZE];int top;}SeqStack, *PSeqStack;PSeqStack Init_SeqStack() //栈的初始化{PSeqStack S;S=(PSeqStack)malloc(sizeof(SeqStack));if (S)S->top=-1;return S;}int Empty_SeqStack(PSeqStack S) //判栈空{if (S->top==-1)return 1;elsereturn 0;}int Push_SeqStack (PSeqStack S, DataType x) //入栈{if (S->top==MAXSIZE-1)return 0; //栈满不能入栈else{S->top++;S->data[S->top]=x;return 1;}}int Pop_SeqStack(PSeqStack S ,DataType *x) //出栈{if (Empty_SeqStack ( S ) )return 0; //栈空不能出栈else{*x=S->data[S->top];S->top--;return 1;}}void Destory_Seqstack(PSeqStack *S) //销毁栈{if(*S)free(*S);*S=NULL;return;}int mazepath(int maze[][n+2],item move[],int x0,int y0) //非递归算法求解迷宫{PSeqStack S;DataType temp;int x,y,d,i,j;temp.x=x0;temp.y=y0;temp.d=-1;S=Init_SeqStack();if(!S){printf("栈初始化失败!");return (0);}Push_SeqStack (S, temp);while(!Empty_SeqStack(S)){Pop_SeqStack(S ,&temp);x=temp.x;y=temp.y;d=temp.d+1;while(d<4){i=x+move[d].x;j=y+move[d].y;if(maze[i][j]==0){temp.x=x;temp.y=y;temp.d=d;Push_SeqStack (S, temp);x=i;y=j;maze[x][y]=-1;if(x==m&&y==n){printf("\n非递归算法求解的迷宫路径为(顺序为从出口到入口输出):\n");while(!Empty_SeqStack(S)){Pop_SeqStack(S,&temp);printf("(%d %d) <- ",temp.x,temp.y);}printf("\n\n................................................................................\n");Destory_Seqstack(&S);return 1;}elsed=0;}elsed++;}}Destory_Seqstack(&S);return 0;}int path(int maze[][n+2],item move[],int x,int y,int step) //递归算法求解迷宫{int i;step++;maze[x][y]=step;if(x==m&&y==n)return 1;for(i=0;i<4;i++){if(maze[x+move[i].x][y+move[i].y]==0)if(path(maze,move,x+move[i].x,y+move[i].y,step))return 1;}step--;maze[x][y]=0;return 0;}void print_way(int maze[][n+2],item move[]) //打印递归算法求解迷宫的路径{int i,j;if(path(maze,move,1,1,1)){printf("\n找到路径的矩阵形式输出如下:\n");for(i=0;i<m+2;i++){for(j=0;j<n+2;j++)printf("%d ",maze[i][j]);printf("\n");}printf("\n");printf("递归算法求解的迷宫路径为(顺序为从入口到出口输出):\n");for(i=0;i<m+2;i++)for(j=0;j<n+2;j++)if(maze[i][j]>1)printf("(%d %d) -> ",i,j);printf("\n\n................................................................................\n");}elseprintf("无法找到路径!\n");}void copy(int maze[][n+2],int ms[][n+2]) //复制原始迷宫序列函数{for(int i=0;i<m+2;i++){for(int j=0;j<n+2;j++)ms[i][j]=maze[i][j];}}void main(){int maze[m+2][n+2];item move[4];int i,j,Q;printf("请输入迷宫序列:\n");for(i=0;i<m+2;i++){for(j=0;j<n+2;j++)scanf("%d",&maze[i][j]);}printf("\n");move[0].x=0;move[0].y=1;move[1].x=1;move[1].y=0;move[2].x=0;move[2].y=-1;move[3].x=-1;move[3].y=0;printf("\n");int mase1[m+2][n+2];copy(maze,mase1);printf("********************************走迷宫******************************************\n");printf("\n");printf("1. 非递归形式走迷宫\n");printf("2. 递归形式走迷宫\n");printf("3. 退出\n");printf("********************************求解方式****************************************\n");while(1){printf("\n请选择(选择0退出)::");scanf("%d",&Q);switch(Q){case 1:mazepath(maze,move,1,1);break;case 2:print_way(mase1,move);break;case 0:exit(0);}}}六.运行与测试七.总结在这个课程设计中,遇到的主要问题是选择了一种实现方法后,在选择另一种时不会输出结果,但是当我把这两个程序分开调试时都会出现结果,结果还是正确的,后来经过分析知道原来是调用完一种方法后,原来输入的迷宫序列可能被改变了,因此,又增加了一个复制原始迷宫序列的函数,对原始序列进行了保存,然后在调用时就出现结果了。

相关主题