栈的应用–迷宫求解
思路: 从一个起点(1,1)坐标开始, 依次判断它的右,下,左,上, 方位能不能走 如果能就直接走, 每走一步将这个位置的坐标入栈,
并且标记为2, 若都不能走, 说明走到死路了, 要开始回溯,走过没有走过标记为3 回溯时就是把入栈的坐标出栈, 即可原路返回,
每返回一步就重新再判断它的 右,下,左,上, 能不能走,直到找到终点(8,8)坐标,否则没有通路
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <malloc.h> //动态存储分配函数头文件,用于栈的存储空间的分配
typedef int DirectiveType; //下一个通道的方向
#define RANGE 100 //迷宫大小
#define STACK_INIT_SIZE 100 //定义栈的初始大小
#define STACKINCREMENT 10 //定义栈的存储增量,在栈长度越界时
#define OK 1
#define ERROR 0
#define ROW 10 //迷宫的行数
#define COL 10 //迷宫的列数
typedef int Status;
typedef struct{
int m,n;
int arr[RANGE][RANGE]; //迷宫数组
}MazeType; //迷宫的类型
typedef struct{
int row; //迷宫的行
int col; //迷宫的列
}PosType; //坐标(row,col)
typedef struct{
int step; //当前位置路径的序号
PosType seat; //当前位置坐标位置
DirectiveType di; //往下一个坐标位置的方向
}SElemType;
typedef struct{
SElemType *base; //栈底
SElemType *top; //栈顶
int stacksize; //栈的大小
}SqStack; //定义栈
//初始化栈
Status InitStack(SqStack &s){
s.base = (SElemType *)malloc (STACKINCREMENT * sizeof (SElemType ));
if(!s.base ){
exit(-2);
}
s.top = s.base ;
s.stacksize = STACK_INIT_SIZE;
return OK;
}
//当栈是不为空时,返回栈顶元素
Status GetTop(SqStack s,SElemType &e){
if(s.top = s.base ){
return ERROR;
}
e = *(s.top - 1);
return OK;
}
//在栈是中插入元素e,入栈
Status PushStack(SqStack &s,SElemType e){
if(s.top - s.base >= s.stacksize){ //若栈满,追加存储空间
s.base = (SElemType *)realloc(s.base,(s.stacksize + STACKINCREMENT )*sizeof (SElemType ));
if(!s.base){
exit(-2);
}
s.top = s.base + s.stacksize;
s.stacksize += STACKINCREMENT;
}
*s.top++ = e;
return OK;
}
//在栈s中删除栈顶,出栈
Status PopStack(SqStack &s,SElemType &e){
if(s.top == s.base){
return ERROR;
}
e = *--s.top;
return OK;
}
//判断栈是否为空
Status StackEmpty(SqStack s){
if(s.base == s.top )
return OK;
return ERROR;
}
//销毁栈
Status DestorySatck(SqStack &s){
free(&s);
return OK;
}
//初始化迷宫
Status InitMaze(MazeType &maze,int a[ROW][COL],int row,int col){
int i,j;
//设置迷宫maze的初值,包括加上边缘一圈的值
for(i = 1;i<row;i++){
for(j=1;j<col;j++){
maze.arr[i][j] = a[i][j];
}
}
//加上围墙
for(i= 0;i<row;i++){
maze.arr[0][i] = maze.arr[row-1][i] = 1; //第0行和第9行为1
}
for(j = 0;j<col;j++){
maze.arr[j][0] = maze.arr[j][col-1] = 1; //第0列和第9列为1
}
return OK;
}
//判断当前节点是否通过,(迷宫数组,当前位置坐标)
Status Pass(MazeType maze,PosType curpos){
//当节点为0时,表示有路
if(maze.arr[curpos .row][curpos .col] == 0){
return OK;
}else {
return ERROR;
}
}
//留下标记
Status FootPrint(MazeType &maze,PosType curpos){
maze.arr[curpos.row][curpos .col] = 2; //走过且走得通
return OK;
}
//留下不能通过的标记
Status MarkPrint(MazeType &maze,PosType curpos){
maze.arr[curpos .row][curpos .col] = 3;
return OK;
}
//创建元素e
SElemType CreateSElem(int step,PosType pos,int di){
SElemType e;
e.step = step;
e.seat = pos;
e.di = di;
return e;
}
//返回当前节点的下一个节点 (当前位置坐标,下一个位置方向)
PosType NextPos(PosType curpos ,DirectiveType di){
PosType pos = curpos ;
switch(di){
case 1:pos.col++;break; //右
case 2:pos.row++;break; //下
case 3:pos.col--;break; //左
case 4:pos.row--;break; //上
}
return pos;
}
//判断是不是出口
Status PosEqual(PosType pos1,PosType pos2){
if(pos1.row == pos2.row && pos1.col == pos2.col){
return OK;
}else
return ERROR;
}
//打印路径
void PrintMaze(MazeType maze,int row,int col){
int i,j;
printf(" ");
for (i = 0; i<col; i++) //打印列数名
printf("%d ", i);
printf("\n");
for (i = 0; i<row; i++){
printf("%d",i); //打印行数名
for (j = 0; j<col; j++){
//printf("%d ",maze.arr[i][j]);
switch (maze.arr[i][j]){
case 0:printf(" "); break; //没走过,但是通路
case 1:printf("■");break; //墙,障碍物
case 2:printf("# ");break; //走过且走得通
case 3:printf("* ");break; //走过但走不通,死胡同
default:break;
}
}
printf("\n");
}
}
//求解迷宫maze中,从入口start到出口end的一条路径
Status MazePath(MazeType &maze,PosType start,PosType end){
SqStack s; //定义栈
SElemType e;
InitStack (s); //初始化栈
PosType curpos = start;
int curstep = 1; //搜索第一步
do{
//如果当前位置可以通过,即是未曾走到的路径
if(Pass(maze,curpos)){
FootPrint (maze,curpos); //留下标记
e = CreateSElem (curstep,curpos,1); //创建元素
PushStack(s,e); //加入路径
if(PosEqual(curpos,end)){ //判断是不是出口
return OK;
}
curpos = NextPos(curpos,1); //获取下一个节点,当前位置的右边
curstep++;
}else{ //当前位置不能通过
if(!StackEmpty(s)){
PopStack(s,e);
while(e.di == 4 && !StackEmpty(s)){ //找寻了四个方向
MarkPrint(maze,e.seat);
PopStack(s,e);
}
if(e.di<4){
e.di++; //换下一个方向
PushStack(s,e);
curpos = NextPos (e.seat,e.di); //设定当前位置是该方向上的相邻块
}
}
}
}while(!StackEmpty (s));
return OK;
}
Status main(){
int i,j;
PosType start ,end; //开始,终点坐标
MazeType maze;
int a[ROW][COL] = {
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,1,0,0,1,0,1},
{1,0,0,1,0,1,0,1,1,1},
{1,1,0,0,0,1,0,0,0,1},
{1,0,1,1,0,0,1,1,0,1},
{1,1,0,0,1,0,0,0,1,1},
{1,0,1,0,0,0,1,1,0,1},
{1,0,1,0,1,1,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1}
};
printf("\n原始迷宫如下:\n");
printf("(其中‘1’表示墙,‘0’表示通道)\n");
for(i = 0;i < 10;i++){
for(j = 0;j < 10;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
InitMaze(maze,a,ROW,COL); //初始化迷宫
start.row = 1; //给定迷宫起点坐标(1,1)
start.col = 1;
end.row = 8;
end.col = 8; //给定迷宫终点坐标(8,8)
if (MazePath(maze, start,end)){ //如果找到一条路径
printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("\n求解迷宫路径如下:\n");
printf("(其中'#'表示求解路径,'*'表示死胡同)\n");
PrintMaze(maze, ROW,COL); //输出迷宫路径
}else
printf("\n从入口(1,1)到出口(8,8)没有通路!\n");
return OK;
}