数据结构--栈的应用 ( 迷宫问题 )

迷宫问题 : 

其中要使用栈    栈的定义和基本操作 : 传送门  https://blog.csdn.net/ds19980228/article/details/81741617

简单迷宫 :  

0    0    0    0    0    0  

0    0    1    0    0    0  

0    0    1    0    0    0  

0    0    1    1    1    0  

0    0    1    0    1    1  

0    0    1    0    0    0

简单迷宫 (如上图所示 ) : 当我们找出它的通路时, 可以直接利用栈的性质, 从起点开始将所走的路径以下标的方式存入栈, 并且将原来坐标所存的值标记为2, 证明已经走过,  那么周围没有路径可走时, 将栈顶坐标出栈, 再次寻找可走路径, 当栈为空或者达到定义的出口时结束 .这种方法称作回溯法  ( 走完之后如下图所示 )

简单迷宫 :  

0    0    0    0    0    0  

0    0    2    0    0    0  

0    0    2    0    0    0  

0    0    2    2    2    0  

0    0    2    0    2    2  

0    0    2    0    0    0

上面是简单迷宫的处理方法, 那如果迷宫复杂一点的话( 如下图所示 )那又该如何处理呢 ? 

多通路迷宫 : 通路间不带环

0    0    0    0    0    0  

0    1    1    1    1    1  

0    1    0    0    0    0  

0    1    0    0    0    0  

0    1    1    1    1    1  

0    1    0    0    0    0

多通路迷宫 : 通路带环

0    0    0    0    0    0  

0    1    1    1    0    0  

0    1    0    1    0    0  

0    1    0    1    0    0  

0    1    1    1    1    1  

0    1    0    0    0    0

当然上面的方法也能求解出通路不带环问题, 但是如果遇到带环或者要求出迷宫中最短路径呢 ? 这样就不能用上面的问题求解了, 下面介绍一种方法 : 

当找迷宫通路时候, 每走一步将坐标入栈的同时将坐标位置的值改为上一个坐标点值加 1, 当然第一个入栈坐标代表的值要改为 2 ;

然后判断是否可以通行的条件就变为 :

  • 当下一个坐标的值为 1 可以通行 
  • 当下一个坐标的值比当前坐标值大于 2 可以通行
  • 当无路可走且栈不为空时, 出栈 , 栈为空时结束

若要求出最小的路径只需要将每次到出口时的路径求出, 并且与下次新出口的路径进行比较, 保持路径最小

演示 : 

 

第一遍走 :                                                             第二遍走

0    0    0    0    0    0            0    0    0    0    0    0  

0    6    7    8    0    0            0    6    7    8    0    0

0    5    0    9    0    0            0    5    0    7    0    0

0    4    0   10   0    0            0    4    0    6    0    0

0    3   12  11  12  13           0    3    4    5    6    7

0    2    0    0    0    0            0    2    0    0    0    0

代码如下 : 

//检查是否有通路
int CheckAccess(Pos next,Pos cur)
{
        //判断是否有通路的条件
	if ((next._col > 0 && next._col<N&&next._row>0 && next._row < N) &&
(maze[next._row][next._col] == 1 || maze[next._row][next._col] > maze[cur._row][cur._col] + 1))
		return 1;
	else
		return 0;
}
//寻找最短通路
void MazeGetShortPath(Pos entry)
{
	int i, j;
	int arr[N][N] = {0};
	Stack path;
	Pos cur;
	Pos next;
	int len = 0;
	StackInit(&path);
	StackPush(&path, entry);
	cur = StackTop(&path);
	maze[cur._row][cur._col] = 2;
	while (StackEmpty(&path))
	{
		cur = StackTop(&path);
                //当找到出口时,求出路径长度
		if (cur._col == 5)
		{
                        //如果旧路径小于新路径或者len为0时,则更新len的大小,并且用两个辅助栈
                        //记录该路径所走的路线
			if (len == 0 || len > StackSize(&path))
			{
                                Stack back;            
	                        Stack Path;
				len = StackSize(&path);
				StackInit(&Path);
				StackInit(&back);
                                //将最短路径所走的路线存在Path里边
				while (StackEmpty(&path))
				{
					StackPush(&back, StackTop(&path));
					StackPush(&Path, StackTop(&path));
					StackPop(&path);
				}
                                //还原原始栈
				while (StackEmpty(&back))
				{
					StackPush(&path, StackTop(&back));
					StackPop(&back);
				}
			}
		}
		//检查上边是否通路
		next = cur;
		next._row -= 1;
		if (CheckAccess(next, cur))
		{
			StackPush(&path, next);
			maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
			continue;
		}
                //检查下边是否有通路
		next = cur;
		next._row += 1;
		if (CheckAccess(next, cur))
		{
			StackPush(&path, next);
			maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
			continue;
		}
                //检查左边是否有通路
		next = cur;
		next._col -= 1;
		if (CheckAccess(next, cur))
		{
			StackPush(&path, next);
			maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
			continue;
		}
                //检查右边是否有通路
		next = cur;
		next._col += 1;
		if (CheckAccess(next, cur))
		{
			StackPush(&path, next);
			maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
			continue;
		}
                //若无通路栈顶元素出栈
		StackPop(&path);
	}
	printf("最短路径长度为:%d", len);
	printf("\n");
	printf("所走路径如下图:");
	while (StackEmpty(&Path))
	{
		arr[StackTop(&Path)._row][StackTop(&Path)._col] = -1;
		StackPop(&Path);
	}
	printf("\n");
	for (i = 0; i < N; i++)
	{
		for (j = 0; j < N; j++)
			printf("%2d ", arr[i][j]);
		printf("\n");
	}
}

完整代码 : 

栈之前已经实现过, 直接拿来用即可

Maze.h

#pragma once
#define N 6
static  int maze[N][N] = { 0, 0, 0, 0, 0, 0,
			   0, 1, 1, 1, 0, 0,
			   0, 1, 0, 1, 0, 0,
			   0, 1, 0, 1, 0, 0,
			   0, 1, 1, 1, 1, 1,
			   0, 1, 0, 0, 0, 0 };
//数据结构
typedef struct Pos
{
	int _row;
	int _col;
}Pos;
//寻找最短路径,并且打印最短路线
void MazeGetShortPath(Pos entry);
//打印迷宫
void PrintMaze()

Maze.c

#include "Maze.h"
//栈的头文件  
#include "Stack.h"  
//检查是否有通路
int CheckAccess(Pos next,Pos cur)
{
	if ((next._col > 0 && next._col<N&&next._row>0 && next._row < N) &&
		(maze[next._row][next._col] == 1 || maze[next._row][next._col] > maze[cur._row][cur._col] + 1))
	//判断条件
		return 1;
	else
		return 0;
}
//打印迷宫
void PrintMaze()
{
	int i, j;
	printf("\n");
	for (i = 0; i < N; i++)
	{
		for (j = 0; j < N; j++)
			printf("%2d ", maze[i][j]);
		printf("\n");
	}
}
//寻找最短通路
void MazeGetShortPath(Pos entry)
{
	int i, j;
	int arr[N][N] = {0};
	Stack back;
	Stack path;
	Stack Path;
	Pos cur;
	Pos next;
	int len = 0;
	StackInit(&path);
	StackPush(&path, entry);
	cur = StackTop(&path);
	maze[cur._row][cur._col] = 2;
	while (StackEmpty(&path))
	{
		cur = StackTop(&path);
		if (cur._col == 5)
		{
			if (len == 0 || len > StackSize(&path))
			{
				len = StackSize(&path);
				StackInit(&Path);
				StackInit(&back);
				while (StackEmpty(&path))
				{
					StackPush(&back, StackTop(&path));
					StackPush(&Path, StackTop(&path));
					StackPop(&path);
				}
				while (StackEmpty(&back))
				{
					StackPush(&path, StackTop(&back));
					StackPop(&back);
				}
			}
		}
		//检查上边是否通路
		next = cur;
		next._row -= 1;
		if (CheckAccess(next, cur))
		{
			StackPush(&path, next);
			maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
			continue;
		}
		next = cur;
		next._row += 1;
		if (CheckAccess(next, cur))
		{
			StackPush(&path, next);
			maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
			continue;
		}
		next = cur;
		next._col -= 1;
		if (CheckAccess(next, cur))
		{
			StackPush(&path, next);
			maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
			continue;
		}
		next = cur;
		next._col += 1;
		if (CheckAccess(next, cur))
		{
			StackPush(&path, next);
			maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
			continue;
		}
		StackPop(&path);
	}
	printf("最短路径长度为:%d", len);
	printf("\n");
	printf("所走路径如下图:");
	while (StackEmpty(&Path))
	{
		arr[StackTop(&Path)._row][StackTop(&Path)._col] = -1;
		StackPop(&Path);
	}
	printf("\n");
	for (i = 0; i < N; i++)
	{
		for (j = 0; j < N; j++)
			printf("%2d ", arr[i][j]);
		printf("\n");
	}
}

Test.c

#include "Stack.h"
#include "Maze.h"
int main()
{
	Pos entry;
	entry._row = 5;
	entry._col = 1;
	PrintMaze();
	printf("\n");
	MazeGetShortPath(entry);
	PrintMaze();
	system("pause");
	return 0;
}

调试结果如下 : 

    

 

 

  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值