迷宫问题——c语言栈实现

《迷宫问题——c语言栈实现》

我们用一个二维数组表示迷宫的点,1能走,0不能走,用回溯法写,用一个简单一点的迷宫做事例:

#define _CRT_SECURE_NO_WARNINGS 1

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#define N 6 //N*N的迷宫
#define length N * N//最大行走步数

typedef struct Pos
{
	int x;//横坐标0到N-1
	int y;//纵坐标0到N-1
}Pos;

typedef struct Stack
{
	Pos* _top;//栈顶指针
	Pos* _end;//栈底指针
	int stackSize;//栈的容量
}Stack;

void pathPrint();//打印路径
void MazeGetShortPath(Pos entry, Stack* path);//从第一部开始走
void myStackInit(Stack* s);//栈初始化
void zoulu(Pos now, int* arr);//走每一步的判断以及递归
void myStackPush(Stack* s, Pos x);//压入栈
Pos myStackPop(Stack* s);//弹出栈
int StackEmpty(Stack* s);//判空栈

Stack Path;//定义路径栈
Stack* s = &Path;//定义路径栈的指针,指向这个存放路径栈
Pos enterPoint;//起点
Pos finalPoint;//终点
int count = 0;//统计一共多少种走法



//------------------分割线,以上皆为头文件-----------------------------



void pathPrint()
{
	int x = 0;
	int y = 0;
	int i = 0;
	Pos* tmp = s->_end;//把栈底备份
	while (s->_top != s->_end)
	{
		i++;//第i步走到哪个格子
		x = s->_end->x;
		y = s->_end->y;
		s->_end++;
		printf("第%d步:(%d,%d)\n", i, x, y);
	}
	s->_end = tmp;//_end指针回到栈底
}

void zoulu(Pos now, int arr[N][N])
{
	if (finalPoint.x == now.x && finalPoint.y == now.y)//如果now点是终点,输出走法,并返回
	{
		count++;//给出路总数+1
		printf("--------第%d种走法--------\n",count);
		pathPrint();//打印步骤
		Pos p = myStackPop(s);//弹出终点
		arr[p.x][p.y] = 1;//重置终点可走(退回看看有没有别的走法)
		return;
	}
	//没到终点的情况:
	if (1 == arr[now.x - 1][now.y] && now.x - 1 >= 0)//如果now点的上面可以走并且不超过棋盘
	{
		Pos nowup;//创建一个now上面的点
		nowup.x = now.x - 1;
		nowup.y = now.y;
		myStackPush(s, nowup);//吧点压入栈
		arr[now.x - 1][now.y] = -1;//标记走过
		zoulu(nowup, arr);//走到上面一个点
	}
	if (1 == arr[now.x + 1][now.y] && now.x + 1 < N)//下面的点可走
	{
		Pos nowdn;
		nowdn.x = now.x + 1;
		nowdn.y = now.y;
		myStackPush(s, nowdn);
		arr[now.x + 1][now.y] = -1;//标记走过
		zoulu(nowdn, arr);
	}
	if (1 == arr[now.x][now.y - 1] && now.y - 1 >= 0)//左边点
	{
		Pos nowlf;
		nowlf.x = now.x;
		nowlf.y = now.y - 1;
		myStackPush(s, nowlf);
		arr[now.x][now.y - 1] = -1;//标记走过
		zoulu(nowlf, arr);
	}
	if (1 == arr[now.x][now.y + 1] && now.y + 1 < N)//右边点
	{
		Pos nowrg;
		nowrg.x = now.x;
		nowrg.y = now.y + 1;
		myStackPush(s, nowrg);
		arr[now.x][now.y + 1] = -1;//标记走过
		zoulu(nowrg, arr);
	}
	//如果都不可以走,说明是当前走的这条路的死路,就弹出这个点,并且重置。
	//当前递归层次结束会返回到上次调用的地方,并不会走重复路,这是代码核心。
	Pos p = myStackPop(s);
	arr[p.x][p.y] = 1;
}

void MazeGetShortPath(Pos entry, Stack* path, int arr[N][N])
{
	myStackPush(path, entry);//吧起点压入后就开始走路
	arr[entry.x][entry.y] = -1;//标记走过
	zoulu(*(s->_top - 1), arr);
}

void myStackInit(Stack* s)
{
	//给栈申请空间
	s->_end = (Pos*)malloc(length * sizeof(Pos));
	//判断是否申请成功
	if (!s->_end)
	{
		exit(0);
	}
	//初始化栈数组空间
	s->_top = s->_end;//最开始栈顶等于栈低
	s->stackSize = length;
	return;
}

void myStackPush(Stack* s, Pos x)
{
	//断言
	assert(s);
	if (s->stackSize == s->_top - s->_end)//判断栈空间是不是满了,满了就追加空间(动态栈)
	{
		printf("空间已满,追加空间");
		s->_end = (Pos*)realloc(s->_end, (s->stackSize + length) * sizeof(Pos));
		if (!s->_end)
		{
			exit(0);
		}
		s->_top = s->_end + s->stackSize;//设置栈顶
		s->stackSize += length;//设置栈长度
	}
	*(s->_top) = x;//设置x
	s->_top++;//指针后移
	return;
}

int StackEmpty(Stack* s)
{
	return 0 == (s->_top - s->_end);//或者判断两个指针是否相等也可以
}

Pos myStackPop(Stack* s)
{
	assert(s);
	if (StackEmpty(s))
	{
		printf("栈为空");
		return;
	}
	return *--(s->_top);//栈顶指针下移并取出那个值
}

int main()
{
	//二维数组:1表示可以走,0表示不可以走
	int maze[N][N] =
	{
		{ 0, 0, 0, 0, 0, 0 },
		{ 1, 1, 1, 1, 1, 0 },
		{ 1, 0, 1, 0, 1, 0 },
		{ 1, 0, 1, 1, 1, 0 },
		{ 1, 0, 0, 0, 1, 1 },
		{ 1, 1, 1, 1, 1, 0 },
	};
	//设置起点和终点坐标
	enterPoint.x = 5;
	enterPoint.y = 2;
	finalPoint.x = 4;
	finalPoint.y = 5;
	//初始化栈
	myStackInit(s);
	//开始走了
	MazeGetShortPath(enterPoint, s, &maze);

	system("pause");
	return 0;
}

结果为:

《迷宫问题——c语言栈实现》

 

    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/likunkun__/article/details/81741860
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞