【数据结构】求简单迷宫是否存在路径(递归和非递归版)

求简单迷宫是否存在路径


代码中用到的栈代码如下:

stack.h

#pragma once

#include<stdio.h>
#include<stddef.h>
#include"Maze.h"

typedef Pos SeqType;

#define SEQDATAMAX 1000

/*创建一个栈的结构体*/
typedef struct SeqStack{
	SeqType data[SEQDATAMAX];
	int top;
	int bottom;
}SeqStack;


/*初始化栈*/
void SeqStackInit(SeqStack* seq);
/*从栈里面压入一个元素*/
void SeqStackPush(SeqStack* seq, SeqType value);
/*出栈一个元素*/
void SeqStackPop(SeqStack* seq);
/*取栈顶元素*/
SeqType SeqStackTopValue(SeqStack* seq);
/*销毁栈*/
void SeqStackDestory(SeqStack* seq);
/*判断当前栈是不是空栈*/
int SeqStackEmpty(SeqStack* seq);


stack.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"

/*初始化栈*/
void SeqStackInit(SeqStack* seq) {

	seq->top = 0;
	seq->bottom = seq->top;
}
/*从栈里面压入一个元素*/
void SeqStackPush(SeqStack* seq, SeqType value) {

	if (seq == NULL) {
		return;
	}
	/*判断栈是不是已经满了*/
	if (seq->top == SEQDATAMAX - 1) {
		return;
	}
	seq->top++;
	seq->data[seq->top] = value;
}
/*删除栈顶元素,出栈一个元素*/
void SeqStackPop(SeqStack* seq) {

	if (seq == NULL) {
		return;
	}
	/*判断栈是否为空栈*/
	if (seq->top == seq->bottom) {
		printf("栈为空");
		return;
	}
	seq->top--;
}
/*取栈顶元素*/
SeqType SeqStackTopValue(SeqStack* seq) {

	if (seq == NULL) {
		return;
	}
	return seq->data[seq->top];
}

/*销毁栈*/
void SeqStackDestory(SeqStack* seq) {

	if (seq == NULL) {
		return;
	}
	seq->top = 0;
}


/*判断当前栈是不是空栈*/
int SeqStackEmpty(SeqStack* seq) {
	if (seq == NULL) {
		return;
	}
	if (seq->top == seq->bottom) {
		return 1;
	}
	return 0;
}



非递归版代码如下:

maze.h

#pragma once

#include<stdio.h>

typedef struct Pos{
	int _Row;
	int _COL;
}Pos;

int maze[5][5] = { { 0, 1, 0, 0, 0 },
{ 0, 1, 1, 1, 0 },
{ 0, 1, 0, 1, 1 },
{ 1, 1, 0, 1, 0 },
{ 0, 0, 0, 1, 0 },
};
typedef struct Maze{

	struct Pos pos;

}Maze;


maze.c

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdlib.h>
#include"Maze.h"
#include"Stack.h"

/*判断当前点能否落脚*/
int CanStay(Pos* pos) {
	if (pos == NULL) {
		return;
	}
	/*行和列 小于0, 或者行也列大于5*/
	if (pos->_Row < 0 || pos->_COL < 0
		|| pos->_Row > 4 || pos->_COL > 4) {
		/*表示该点的行和列在迷宫外面*/
		return 0;
	}
	return 1;
}

/*标记当前点*/
void Mark(Pos* Pos, int Maze[5][5]) {
	if (Pos == NULL) {
		return;
	}
	Maze[Pos->_Row][Pos->_COL] = 2;
}
/*判断该点是不是出口*/
int Check_Export(Pos* Pos, int Maze[5][5]) {

	if (Pos == NULL) {
		return;
	}

		/*该点在迷宫地图内*/
		/*该点在地图边界*/
		if (Pos->_Row == 0 || Pos->_COL == 0 || Pos->_Row == 4 || Pos->_COL == 4) {

			if (Maze[Pos->_Row][Pos->_COL] == 1) {
				/*该点等于1,是出口*/
				return 1;
			}
		}
	return 0;
}

/*判断是否能形成通路*/
int Can_go(Pos* pos, int Maze[5][5]) {

	if (pos == NULL) {
		return;
	}
	/*如果当前点为1,则可以走*/
	if (Maze[pos->_Row][pos->_COL] == 1) {
		return 1;
	}
	return 0;
}

/*得到出口路径*/
/*传入入口点和一个地图*/
int Get_Path(Maze* entry, int Maze[][5]) {
	if (entry == NULL) {
		return;
	}
	/*判断入口点能否落脚*/
	if (!CanStay(entry)) {
		return;
	}
	SeqStack seq;
	SeqStackInit(&seq);

	//标记入口点,然后入栈入口点
	Mark(entry, Maze);
	SeqStackPush(&seq, entry->pos);
	Pos pos;
	pos = entry->pos;
	/*进入循环,循环停止条件是走到出口*/
	while (!Check_Export(&pos, Maze)) {

		/*进入循环了已经把入口点标记了,然后开始判断当前的点周围的四个点是否可以走*/

		/*上*/
		/*当前点的行加个1*/
		pos._Row -= 1;
		/*如果能落脚,在地图上*/
		if (CanStay(&pos, Maze)) {
			/*判断该点是否能走*/
			if (Can_go(&pos, Maze)) {
				/*能走,判断是否为出口点*/
				if (Check_Export(&pos, Maze)) {
					break;
				}
				/*,标记该点把该点入栈*/
				Mark(&pos, Maze);
				SeqStackPush(&seq, pos);
				continue;
			}
		}
		pos._Row += 1;

		
		/*下*/
		pos._Row += 1;
		if (CanStay(&pos, Maze)) {
			if (Can_go(&pos, Maze)) {
				/*可以走*/
				if (Check_Export(&pos, Maze)) {
					break;
				}
				Mark(&pos, Maze);
				SeqStackPush(&seq, pos);
				continue;
			}
		}
		pos._Row -= 1;

		/*左*/
		pos._COL -= 1;
		if (CanStay(&pos, Maze)) {
			if (Can_go(&pos, Maze)) {
				/*可以走*/
				/*判断是不是出口点,如果是,就直接退出,找到该点了*/
				if (Check_Export(&pos, Maze)) {
					break;
				}
				Mark(&pos, Maze);
				SeqStackPush(&seq, pos);
				continue;
			}
		}
		pos._COL += 1;

		/*右*/
		pos._COL += 1;
		if (CanStay(&pos, Maze)) {
			if (Can_go(&pos, Maze)) {
				/*可以走*/
				if (Check_Export(&pos, Maze)) {
					break;
				}
				Mark(&pos, Maze);
				SeqStackPush(&seq, pos);
				continue;
			}
		}
		pos._COL -= 1;

		
		/*每个点都走不了了,如果这个点是入口点,表示没有出口?*/
		if (pos._COL == entry->pos._COL && pos._Row == entry->pos._Row) {
			return 0;
		}
		/*
		**每个点都走不了了
		**这个时候出栈一个元素
		**然后让pos等于当前栈的栈顶元素(回溯)
		*/
		SeqStackPop(&seq);
		pos = SeqStackTopValue(&seq);
	}
	/*如果退出while循环,表示找到了出口点*/
	return 1;
}


int main() {

	/*只是判断有无出口*/
	Maze entry_pos;
	entry_pos.pos._Row = 0;
	entry_pos.pos._COL = 1;
	int path = Get_Path(&entry_pos,	maze);
	printf("expect 1, actual: %d", path);
	system("pause");
	return 0;
}



递归版代码如下:

maze.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Maze.h"
#include"Stack.h"


int Canstay(Pos* pos) {
	/*判断当前点是否在地图上*/
	if (pos == NULL) {
		return;
	}
	if (pos->_Row < 0 || pos->_COL < 0 ||
		pos->_Row > 4 || pos->_COL > 4) {
		/*该坐标不在地图内*/
		return 0;
	}
	return 1;
}

/*判断该点是否为出口*/
int Check_Export(Pos* pos, int Maze[5][5]) {
	if (pos == NULL) {
		return;
	}
	/*先判断该坐标是否在地图上*/
	if (pos->_Row == 0 || pos->_COL == 0 ||
		pos->_Row == 4 || pos->_COL == 4) {

		if (Maze[pos->_Row][pos->_COL] == 1) {
			printf("出口点坐标为:(%d, %d)", pos->_Row, pos->_COL);
			return 1;
		}
	}
	return 0;
}

/*标记该点*/
void Mark(Pos* pos, int Maze[5][5]) {

	if (pos == NULL) {
		return;
	}
	Maze[pos->_Row][pos->_COL] = 2;
}
/*判断当前点是否是通路*/
int Can_Walk(Pos* pos, int Maze[5][5]) {
	if (pos == NULL) {
		return;
	}
	if (Maze[pos->_Row][pos->_COL] == 1) {
		return 1;
	}
	return 0;
}

int _GetPath(Pos* entry, Pos* pos, int  Maze[5][5]) {
	/*pos就是当前点*/
	if (entry == NULL) {
		return;
	}
	/*判断当前点是否在地图上*/
	if (!Canstay(entry)) {
		return 0;
	}
	/*标记入口点,然后把入口点压栈*/
	Mark(entry, maze);
	//SeqStack seq;
	//SeqStackPush(&seq, *entry);

	/*开始递归*/
	/*递归出口*/
	if (Check_Export(pos, Maze)) {
		return 1;
	}
	else {
		/*如果pos不是出口,就标记它*/
		Mark(pos, Maze);
	}



	/*上*/
	--pos->_Row;
	/*判断坐标是不是在地图上*/
	if (Canstay(pos)) {
		/*如果在地图内,判断该点是否可以走*/
		if (Can_Walk(pos, Maze)) {
			/*把该点标记下*/
			/*判断子问题是否成功找到通路*/
			if (_GetPath(entry, pos, Maze)) {
				return 1;
			}
		}
	}
	++pos->_Row;

	/*下*/
	++pos->_Row;
	if (Canstay(pos)) {
		if (Can_Walk(pos, Maze)) {
			if (_GetPath(entry, pos, Maze)) {
				return 1;
			}
		}
	}
	--pos->_Row;

	/*左*/
	--pos->_COL;
	if (Canstay(pos)) {
		if (Can_Walk(pos, Maze)) {
			if (_GetPath(entry, pos, Maze)) {
				return 1;
			}
		}
	}
	++pos->_COL;
	/*右*/
	++pos->_COL;
	if (Canstay(pos)) {
		if (Can_Walk(pos, Maze)) {
			if (_GetPath(entry, pos, Maze)) {
				return 1;
			}
		}
	}
	--pos->_COL;

	/*到了这里,表示该点走不通*/
	return 0;
}

int main() {
	/*不是最优解最短路径的递归求法*/
	Pos entry;
	Pos pos;
	entry._Row = 0;
	entry._COL = 1;

	pos = entry;
	int i = _GetPath(&entry, &pos, maze);
	printf("expect 1, actual: %d", i);
	system("pause");
	return 0;
}


简单迷宫的递归和非递归代码就这样了,地图在头文件里

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
问题描述: 以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对任意设定的迷宫出从入口(0,0)到出口(m-1,n-1)的通路和通路总数,或得出没有通路的结论。例如下图, 0(入口) 1 0 1 0 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0(出口) 从入口到出口有6条不同的通路。 而下图: 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 0 0 1 0 1 1 1 0 0 0 0 0 0 从入口到出口则没有通路。 算法设计: 给定一个m*n的长方阵表示迷宫,设计算法输出入口到出口的通路和通路总数,或得出没有通路的结论。 算法提示: 和皇后问题与分书问题类似。可以用二维数组存储迷宫数据,对于迷宫中任一位置,均可约定有东、南、西、北四个方向可通。从当前位置a(用(x,y)表示一个位置,假定它是以向右的x轴和向下的y轴组成的平面上的一个点)出发依次尝试四个方向是否有路,若某个方向的位置b可通,则按照同样的方法继续从b出发寻找。若到达出口,则找到一条通路。 数据输入: 由文件input.txt 提供输入数据。第一行是m和n的值,空格分隔,其后共m行。每行有n个数字,数和数之间用空格分隔。 结果输出: 将计算出的所有从入口到出口的通路输出到文件output.txt 中。若没有通路,则将0写入文件中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值