用栈走迷宫

问题描述:

如何求出从入口到出口的一条迷宫路径?

问题思路:

回溯法。从入口开始选定一个方向走,如果这个方向走不通,就换下一个方向,如果走得通,存下这个位置,跳到下一个位置继续判断。如果试完所有方向都不通,那么说明这个位置是死路,标记当前位置已走过,然后回溯到上一个位置继续判断。直到走到终点程序结束。

那么怎么保存走过的位置和回去呢?我们需要一个先进后出的数据结构,栈就满足这个要求,出栈就是返回上一个位置,压栈就是存储当前位置。

数据结构:

我们用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


  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值