基于栈实现解决迷宫问题
栈是一种非常常见的数据结构,在计算机领域被广泛应用,例如操作系统会给每个线程创建一个栈用来存储函数调用时各个函数的参数,返回地址及临时变量等,栈的特点是后进先出,即最后被压入(push)栈的元素会第一个被弹出(pop)。
如下所示给定一个迷宫(“1”表示此路不通,“0”表示此路通过),那么给定一个入口点,如何找到一条通路呢?如果一个迷宫的规模很大,又如何实现呢?给出两种方法:
第一种,可以用一个二维数组来保存迷宫,但是如果迷宫的规模太大,或者我们频繁的更改迷宫时,使用二维数组显然不够机智。
第二种,采用文件的方式来保存迷宫,程序中只用实现读取文件的操作即可,这样便于以后对程序的维护。先将迷宫的入口点压人栈,再对这个点的上、下、左、右方向进行判断,看能否有通过的点,倘若没有,则迷宫中没有一条可以通过的路径,如果存在,则将这个点也压人栈中,循环下去,直到找到没有可以继续进行的点,此时需要“回溯”,即倒回以前走过的点,进而判断有没有刚才没有走过且可以通过的点,仍存在,再次进行刚才的压栈操作,直到走出迷宫为止。否则没有通路。
代码如下:
#pragma once
#define N 10
#include<iostream>
#include<assert.h>
#include <stack>
using namespace std;
//使用静态数组
struct Pos //标记点的位置坐标
{
int _row;
int _col;
};
//void GetMaze(int a[][N], int n)
void GetMaze(int* a, int n)//获取文件中的迷宫
{
assert(a);
FILE* open = fopen("F:\\比特有关书籍\\数据结构\\MazeMap.txt", "r");
assert(open);//判断打开文件是否成功
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; )
{
char ch = fgetc(open);
if (ch == '0' || ch == '1')
{
a[i*n+j] = ch - '0';
++j;//为了防止迷宫中行和列之间的距离
}
else
{
continue;
}
}
}
fclose(open);
}
void PrintMaze(int* a, int n)//打印迷宫
{
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
cout<<a[i*n+j]<<" ";
}
cout<<endl;
}
cout<<endl;
}
bool CheckIsAccess(int* a, int n, Pos next)//检查迷宫结点的下一个路径上的结点
{
assert(a);
if (next._row >= 0 && next._row < n
&& next._col >=0 && next._col < n
&& a[next._row*n+next._col] == 0)
{
return true;
}
else
{
return false;
}
}
//entry 为迷宫的入口位置,path用于保存迷宫的通路
//判断迷宫中是否存在一条通路
bool MazePath(int* a, int n, const Pos& enrty,
stack<Pos>& path)
{
Pos cur = enrty;
path.push(cur);
while (!path.empty())
{
// 是否已经到出口
if (cur._row == n-1)
{
return true;
}
a[cur._row*n + cur._col] = 2;//将压栈后的位置内容进行更改
Pos next = cur;
// 上
next._row--;
if(CheckIsAccess(a, n, next))
{
cur = next;
path.push(cur);
continue;
}
// 右
next = cur;
next._col++;
if(CheckIsAccess(a, n, next))
{
cur = next;
path.push(cur);
continue;
}
// 下
next = cur;
next._row++;
if(CheckIsAccess(a, n, next))
{
cur = next;
path.push(cur);
continue;
}
// 左
next = cur;
next._col--;
if(CheckIsAccess(a, n, next))
{
cur = next;
path.push(cur);
continue;
}
cur = path.top();
path.pop();
}
return false;
}
void TestMaze()
{
int a[N][N] = {};
GetMaze((int*)a, N);
PrintMaze((int*)a, N);
stack<Pos> path;
Pos enrty = {2,0};
bool ret = MazePath((int*)a, N, enrty, path);
cout<<"是否有通路:"<<" "<<ret<<endl;
PrintMaze((int*)a, N);
}