看数据结构写代码(13)栈的应用(四) 迷宫求解

这是一个 用 穷举法 解 迷宫问题 的一个示例,但在 效率 和 解的 最短路径上 就稍显不足了。

这 两个问题,留在 以后 空闲 时刻 解答。

欢迎指出代码不足

下面上代码:

// Maze.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdlib.h>

struct Postion
{
	int x;
	int y;
};

typedef int Direction;

struct ElementType
{
	Postion pos;
	Direction direction;
};

enum E_State
{
	E_State_Error = 0,
	E_State_Ok = 1,
};
//链表节点node
struct lStackNode
{
	ElementType data;
	lStackNode * next;
};

//链栈
struct linkStack
{
	lStackNode * bottom;
	lStackNode * top;
	int len;
};

lStackNode * makeNode(ElementType data){
	lStackNode * pNode = (lStackNode *)malloc(sizeof(lStackNode));
	if (pNode != NULL)
	{
		pNode->data = data;
		pNode->next = NULL;
	}
	return pNode;
}

E_State stackInit(linkStack * lStack){
	//分配头节点
	lStackNode * pNode = (lStackNode *) malloc(sizeof(lStackNode));
	if (pNode == NULL)
	{
		return E_State_Error;
	}
	pNode->next = NULL;
	//栈顶和栈底指向同一个节点时为空.
	lStack->bottom = lStack->top = pNode;
	lStack->len = 0;
	return E_State_Ok;
}

void stackClear(linkStack * stack){
	lStackNode * next = stack->bottom->next;
	while (next != NULL)
	{
		lStackNode * freeNode = next;
		/*又粗心了。。。
		free(freeNode);
		next = next->next;*/
		next = next->next;
		free(freeNode);
	}
	stack->top = stack->bottom;
	//忘记 了
	//错误
	stack->bottom->next = NULL;
	stack->len = 0;
}

void stackDestory(linkStack * stack){
	stackClear(stack);
	free(stack->top);
	stack->top = stack->bottom = NULL;
}

E_State stackGetTop(linkStack stack,ElementType * topData){
	//链表的栈顶 指向 栈顶元素
	if (stack.top != stack.bottom)
	{
		*topData = stack.top->data;
		return E_State_Ok;
	}
	else
	{
		return E_State_Error;
	}
}

int stackLen(linkStack stack){
	return stack.len;
}

bool stackEmpty(linkStack stack){
	return stack.top == stack.bottom ? true : false;
}

E_State stackPush(linkStack * stack,ElementType data){
	lStackNode * node = makeNode(data);
	if (node != NULL)
	{
		stack->top->next = node;
		stack->top = node;
		stack->len++;
	}
	else{
		return E_State_Error;
	}
}

E_State stackPop(linkStack * stack,ElementType * data){
	if (stack->top != stack->bottom)
	{
		//首先指向第一个元素.
		lStackNode * next = stack->bottom;
		*data = stack->top->data;
		//找到栈顶元素的前驱
		while (next->next != stack->top)
		{
			next = next->next;
		}
		free(stack->top);
		next->next = NULL;
		stack->top = next;
		//忘记加了
		stack->len--;
		return E_State_Ok;
	}
	else{
		return E_State_Error;
	}
}

int mazeData[10][10] = {
	{0,0,0,0,0,0,0,0,0,0},
	{0,1,1,0,1,1,1,0,1,0},
	{0,1,1,0,1,1,1,0,1,0},
	{0,1,1,1,1,0,0,1,1,0},
	{0,1,0,0,0,1,1,1,1,0},
	{0,1,1,1,0,1,1,1,1,0},
	{0,1,0,1,1,1,0,1,1,0},
	{0,1,0,0,0,1,0,0,1,0},
	{0,0,1,1,1,1,1,1,1,0},
	{0,0,0,0,0,0,0,0,0,0},
};

//pos坐标的节点 是否 可通过
bool isPass(Postion pos){
	int pass = mazeData[pos.x][pos.y];
	//节点不是障碍物,并且 是没有通过的节点
	return pass == 1 ? true : false;
}

//获取下一个坐标
Postion getNextPos(Postion pos,Direction di){
	int addArray[][2] = {{0,1},{1,0},{0,-1},{-1,0}};
	Postion nextPos;
	nextPos.x = pos.x + addArray[di][0];
	nextPos.y = pos.y + addArray[di][1];
	return nextPos;
}

void footPos(Postion pos,int curStep){
	mazeData[pos.x][pos.y] = curStep;
}

void delPos(Postion pos){
	mazeData[pos.x][pos.y] = -1;
}

int mazePath(Postion startPos,Postion endPos){
	linkStack stack;
	ElementType data;
	int curStep = 2;
	stackInit(&stack);
	do
	{
		if (isPass(startPos))
		{
			footPos(startPos,curStep);
			curStep++;
			data.pos.x = startPos.x;
			data.pos.y = startPos.y;
			data.direction = 0;
			stackPush(&stack,data);
			if (startPos.x == endPos.x && startPos.y == endPos.y)
			{
				stackDestory(&stack);
				return 1;
			}
			else{
				startPos = getNextPos(startPos,0);
			}
		}
		else{
			if (!stackEmpty(stack))
			{
				stackPop(&stack,&data);
				curStep--;
				while (data.direction == 3 && !stackEmpty(stack))
				{
					//错误忘记 删除了..
					delPos(data.pos);
					stackPop(&stack,&data);
					curStep --;
					//startPos.x = data.pos.x;
					//startPos.y = data.pos.y;
				}
				if (data.direction < 3)
				{
					data.direction++; // 换下一个方向探索
					stackPush(&stack,data);
					curStep++;
					startPos = getNextPos(data.pos,data.direction);
				}
			}
		}

	} while (!stackEmpty(stack));
	stackDestory(&stack);
	return 0;
}

// 输出解
void PrintMaze()
{
	int i,j;
	int x = 10,y = 10;
	for(i=0;i<x;i++)
	{
		for(j=0;j<y;j++)
			printf("%3d",mazeData[i][j]);
		printf("\n");
	}
	printf("\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
	printf("初始迷宫如下:\n");
	PrintMaze();
	Postion startPos;
	Postion endPos;
	printf("请输入起始位置 坐标x,y (从0行,0列算起):");
	scanf("%d%d",&startPos.x,&startPos.y);
	printf("请输入终止位置 坐标x,y (从0行,0列算起):");
	scanf("%d%d",&endPos.x,&endPos.y);
	int result = mazePath(startPos,endPos);
	if (result == 1)
	{
		printf("迷宫解如下:(起始地址为2)\n");
		PrintMaze();
	}
	else
	{
		printf("迷宫从 (%d,%d) 至 (%d,%d) 无解\n",startPos.x,startPos.y,endPos.x,endPos.y);
		PrintMaze();
	}
	return 0;
}

初始迷宫 中 0代表 墙,1 代表 通路。

时间: 2024-08-08 07:28:53

看数据结构写代码(13)栈的应用(四) 迷宫求解的相关文章

看数据结构写代码(32) 赫夫曼树编码以及译码

杂谈:最近有点慵懒,不好不好.好几天都没写代码,原本准备上星期完结 树 这一章节的.现在 又耽误了.哎.要抓紧时间啊. 下面直接上代码: 可以到我的网盘下载源代码,或者 直接拷贝下面的源代码 运行 网盘地址:点击打开链接 // HuffmanTree.cpp : 定义控制台应用程序的入口点. //哈弗曼编码,译码 #include "stdafx.h" #include <stdlib.h> #include <cstring> enum E_State { E

看数据结构写代码(9)链栈的实现

在写链栈的时候 和 顺序栈一样 犯了两个错误: 一个是 在 入栈 和 进栈顶时候 忘记 操作 linkstack.len 了,另一个是 在写 stackClear 的时候 犯了一个 低级的内存错误. 这两个问题 都是 粗心造成的. 希望 引以为戒 在做下一个例子:数值转换时,又发现了一个问题:在 stackPop 没有返回 pop元素的值.唉  欢迎指出代码不足 下面上代码: // LinkStack.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h"

看数据结构写代码(8)顺序栈的实现

欢迎指出 代码 不足之处 在写顺序栈的时候 犯了两个错误,:一个是 对栈的 认识不够清楚,栈顶指针的下一个位置为栈顶元素: 另一个是粗心,在用 realloc 分配内存的时候,忽略了元素本身的大小,只写了 元素的个数. 希望引以为戒. 上代码: // SqStack.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <stdlib.h> #include <cstdio> //故意将值设置的比较小,以测试

看数据结构写代码(10)栈的应用(一) 数值转换

首先 修正上一节 stackPop 代码的错误 E_State stackPop(linkStack * stack,elelmentType * data){ if (stack->top != stack->bottom) { //首先指向第一个元素. lStackNode * next = stack->bottom; <strong><span style="font-size:18px;color:#ff6666;">*data =

看数据结构写代码(15)链式队列的实现

队列 和 栈 是 一种 受限制的 线性表.所以 他们的 实现方式 都 相差 无几.之前有过  链栈 和 链式线性表 的 实现经验,自然 写 链队 ,也毫无问题. 下面详细讲解每一段代码 的技术要点 下面是队列节点的数据结构 struct QueueNode { ElementType data; QueueNode * next; }; //生成一个节点 QueueNode * queueNodeMake(ElementType data){ QueueNode * pNode = (Queue

看数据结构写代码(44) 判断无向图是否有环路

在 看 严蔚敏的 数据结构 一书 7.5小节时,书上 说" 判断有向图是否存在环要不无向图复杂.对于无向图来说,深度优先遍历过程中遇到回边(即指向已访问过的顶点的边),则必定存在环路". 看的不明白,所以 网上 百度了一下. 有了思路:故写下算法 和思路,以便以后 温故. 思路: 1.一个n个顶点,e条边的 无向图,若 e>= n,必有环路. 2.若 e < n ,需要 深度 遍历,并把 父节点传入 参数中,如果 遇到 一个 节点 被访问过 并且 不是 父节点,那么 就有环

看数据结构写代码(67) 置换 _ 选择排序(完结篇)

杂谈: 严蔚敏版<数据结构(C语言版)> 一书 终于看完了.这是 一个完结,也是 一个新的开端.<算法导论> 已到手. 置换选择排序的思想 是 将 归并段 尽量 变的 更大,而不是根据 内存 大小 限制在 固定的 大小. 这样 可以 利用赫夫曼树 来 进行 最优归并树,从而 使 外存 读写次数 最少. 下面给出 具体 代码:欢迎指出代码不足. // Replace_Selcetion.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h&q

看数据结构写代码(50)伙伴系统

伙伴系统 是一种 只 可以 分配 2的 幂次方 个 空间的 ,回收 内存 时 只 合并 "伙伴空间" 的一种 动态内存管理方式. 例如 一个 空间 大小 为 64 的 内存,伙伴 系统 为 这 64 的内存  建立 一组 双向循环 链表,分别 管理着  2的 0 次方,2的1 次方幂,2的 2 次方幂...2的6次方幂的 可用空间. 即使 我们 只想分配 一个 大小 为3的 空间,系统 却 只能 返回 一个 内存 大小 为 4(2的2次方)的 一个空间. 系统 在 初始化的 时候 ,并

看数据结构写代码(61) 哈希表

前面说的 各种查找都是 基于 "比较" 的基础 来进行 查找的.查找的 效率 要 看 比较的 次数.那么 有没有 不需要 比较,就可以 找到 想要的数据的 方法呢? 哈希表 就是 这样的 一种方法,它用  数组 作为 保存 关键字的 数据原型,通过 一个 哈希 函数f(k),来找到 关键字 存储的位置,从而 找到想要的信息. 例如 我们 想要解决 这样的一个问题: 假设这有一个各种字母组成的字符串,假设这还有另外一个字符串,而且这个字符串里的字母数相对少一些.什么方法能最快的查出所有小