"迷宫问题(栈)"
“栈”是一种简单的数据结构,它的主要特点就是"先进后出",即就是先压入栈中的数据需要最后出栈。相当于栈是一个杯子,最先放进栈中的东西,只能够最后拿出来。下面对“栈”的特点用图形象的表示出来。
这次所要讨论的是基于栈的迷宫问题,当给定一个迷宫,我们怎样能够找出迷宫中的通道呢?如果迷宫的规模比较大,我们又该如何去实现呢?我们能够明显的知道需要使用一个二维数组用来保存迷宫,但是当迷宫的规模比较大时,或者是当我们想要频繁的去更改所设计的迷宫时,用二维数组的方式显然是不大合理,程序更改会比较麻烦。
在这里我采用“文件”的方式将迷宫进行保存,程序中只用实现读取文件的操作,这样很便于以后对程序的维护。因为动态的给定迷宫大小,程序的实现还是较为麻烦的,这里直接将迷宫的规模给定。用“1”来表示不能够通过,“0”表示能够通过。下面是迷宫的设计:
针对迷宫的特点,主要采用的方法是先将迷宫的入口点压入栈中,在对这个点的上、下、左、右方向的节点进行判断,看是否有能够通过的节点(“0”),若没有,则迷宫中没有一条能够通过的路径,如果存在,则将这个节点也压入栈中,循环这种方式,直到找到没有能够前进的点,此时就要进行“回溯”, 即就是倒回以前走过的点。进而在判断有没有刚才没有走过的且能够通过的节点,若存在,再次进行刚才的压栈操作,直到走出迷宫,若回到迷宫的入口点,则迷宫中不存在通路。
根据上面的思路,编写出下面的代码:
//memory.h文件
#pragma once
#define MAX 10
#include <stack>
#include <assert.h>
//使用静态数组
struct pos //标记点的位置坐标
{
int _row;
int _col;
};
void GetMaze(int * arr, int n) //从文件中获取迷宫
{
assert(arr);
FILE* open = fopen("F:\\keshe\\迷宫问题(栈)\\MazeMap.txt", "r");
assert(open); //判断打开文件是否成功
for (int i = 0; i < MAX; i++)
{
for (int j = 0; j < MAX; )
{
char ch = fgetc(open);
if (ch == '1' || ch == '0')
{
arr[i * n + j] = ch - '0';
j++; //为了防止迷宫中行与列之间的间距
}
}
}
fclose(open);
}
void print(int * arr, int n) //打印迷宫
{
for (int i = 0; i < MAX; i++)
{
for (int j = 0; j < MAX; j++)
{
cout << arr[i * n + j] << " ";
}
cout << endl;
}
}
bool checkIsAccess(int * arr, int n, const pos& next) //检查迷宫节点的下一个路径上的节点
{
assert(arr);
if (next._row >= 0 && next._row < MAX && next._col >= 0 && next._col <= MAX
&& arr[next._row * n + next._col] == 0)
{
return true;
}
return false;
}
//entry 为入口的位置,Paths用来保存迷宫的通路
//判断迷宫中是否存在一条通路
bool SearchMazePaths(int * arr, int n, pos entry, stack<pos> & Paths)
{
assert(arr);
Paths.push(entry);
while (!Paths.empty())
{
pos cur = Paths.top();
arr[cur._row * n + cur._col] = 2; //将压栈后的位置内容进行更改
if (cur._row == (n - 1))
{
return true;
}
pos next = cur;
//上
next._row--;
if (checkIsAccess(arr, n, next))
{
Paths.push(next);
continue;
}
//下
next = cur;
next._row++;
if (checkIsAccess(arr, n, next))
{
Paths.push(next);
continue;
}
//左
next = cur;
next._col--;
if (checkIsAccess(arr, n, next))
{
Paths.push(next);
continue;
}
//右
next = cur;
next._col++;
if (checkIsAccess(arr, n, next))
{
Paths.push(next);
continue;
}
Paths.pop(); //若节点的剩余方向都不能通过,则进行回溯。
}
}
//test.cpp文件
#define _CRT_SECURE_NO_WARNINGS 1
//使用栈来设计迷宫问题
#include <iostream>
using namespace std;
#include <stdlib.h>
#include "memory.h"
int main()
{
int arr[MAX][MAX] = { 0 };
stack<pos> Paths;
pos tmp;
tmp._row = 2;
tmp._col = 0;
GetMaze((int*)arr, MAX);
print((int*)arr, MAX);
cout << endl << endl;
int ret = SearchMazePaths((int *)arr, MAX, tmp, Paths);
printf("能否有一条通路:%d\n\n\n", ret);
print((int*)arr, MAX);
system("pause");
return 0;
}
转载于:https://blog.51cto.com/10740590/1762743