问题描述:
如何求出从入口到出口的一条迷宫路径?
问题思路:
回溯法。从入口开始选定一个方向走,如果这个方向走不通,就换下一个方向,如果走得通,存下这个位置,跳到下一个位置继续判断。如果试完所有方向都不通,那么说明这个位置是死路,标记当前位置已走过,然后回溯到上一个位置继续判断。直到走到终点程序结束。
那么怎么保存走过的位置和回去呢?我们需要一个先进后出的数据结构,栈就满足这个要求,出栈就是返回上一个位置,压栈就是存储当前位置。
数据结构:
我们用m*n的二维数组表示迷宫,0表示墙,1表示可以走,为了防止边界判定,在外面加了一层0(墙),这样数组大小变为(m+2)*(n+2),为了防止死循环,走过之后我们把它标记为-1.
用一个二维数组(8个方向都可以走)来记录方向。
用结构体step来保存位置x,y和要走的方向dir
用存step的栈来实现回溯算法。
最后输出可以走的位置坐标。
c语言代码如下:
/*
用栈实现走迷宫
*/
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#define M 5 //行数
#define N 5 //列数
#define MAX_SIZE (M+2)*(N+2)+1//栈的最大容量是多少个元素
typedef struct step{
int x; //步的x坐标
int y;
int dir;//方向
}step, *pStep;
typedef struct stack{
step e;
pStep base;
pStep top;
int size;
}stack, *pStack;//定义存放步数的栈
//初始化栈
void init(pStack p)
{
if (!p){
printf("NULL\n");
return;
}
p->base = (pStep)malloc(MAX_SIZE*sizeof(step));
if (!p->base)
exit(-1);
p->top = p->base;
p->size = MAX_SIZE;
}
//压栈
void push(pStack p, step st)
{
if (p->top-p->base+1 == p->size){//判断栈满,这里也可以追加存储空间的
printf("Stack full!\n");
return;
}
*p->top++ = st;
}
//出栈
step pop(pStack p)
{
if (p->base == p->top){ //判断栈空
printf("Stack NULL!\n");
exit(-1);
}
p->top--;
return *(p->top);
}
//获得栈顶元素
step getTop(pStack p)
{
if (p->base == p->top){
printf("Stack NULL!\n");
exit(-1);
}
return *(p->top-1);
}
int move[8][8] = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};//存方向的数组
int main()
{
int maze[M+2][N+2] = {
{0, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 0, 0},
{0, 1, 0, 1, 1, 1, 0},
{0, 0, 0, 0, 0, 0, 0}
};//5*5的迷宫,在外面有一层墙,避免边界判定
stack mazeStep;
pStack pmazeStep = &mazeStep;
init(pmazeStep);
int i, j;
int over=0;//判断是否走到终点
step cur;//当前步
cur.x = 1;
cur.y = 1;
cur.dir = 0;
push(pmazeStep, cur);
push(pmazeStep, cur);//将第一步压栈两次,以便输出第一步
while (pmazeStep->base!=pmazeStep->top && over==0)
{
pop(pmazeStep);//将上面不能继续走的步出栈
if (pmazeStep->base != pmazeStep->top)//取栈顶元素,就是返回上一步继续判断
cur = getTop(pmazeStep);
while (cur.dir < 8)
{
i = cur.x+move[cur.dir][0];
j = cur.y+move[cur.dir][1];
if (maze[i][j] == 1){//可以走
maze[i][j] = -1;//代表走过,防止陷入死循环
cur = *(pStep)malloc(sizeof(step));
cur.x = i;
cur.y = j;
cur.dir = 0;
push(pmazeStep, cur);
if (i==M && j == N){
over = 1;
break;
}
}else{
cur.dir++;
}
}
}
if (over == 0)
printf("迷宫无正确路线!\n");
else{
//从栈底到栈顶输出栈中元素
pStep pst;
pst = pmazeStep->base;
while (pst != pmazeStep->top)
{
printf("%d, %d\n", pst->x, pst->y);
pst++;
}
}
return 0;
}
输出结果:
1, 1
2, 2
3, 1
4, 2
5, 3
5, 4
5, 5
Press any key to continue