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

求简单迷宫是否存在路径


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

stack.h

#pragma once

#include
#include
#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

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
#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;
}


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

你可能感兴趣的:(【数据结构】C语言版)