栈的应用-迷宫
看到一个有意思的题目:给一个迷宫,并给定迷宫的起点和终点,然后求出迷宫从入口到出口的路径。
解题思路是这样:
从入口开始,每次沿逆时针方向进行判断,我们总共有四个方向(0.1.2.3),如果方向0不能走,那么我们就试方向1,一直试到可以走的方向。当某一个方向可以走的时候,我们可以往前走一格,然后再进行判断。那么,当然,我们很有可能走到一个死胡同,死胡同的定义是,除了我们来的那个方向,其他三个方向都无法走的通,此时,我们就往后退一个,退到原来的位置,在这个位置上,对之前还没有验证的其他方向进行判断。
比如当前的迷宫式这个样子的(10*10),(1,1)位置是起点,(8,8)位置是终点,X是墙,+是走过得路径,O是小人。当前O所在的位置是(1,7),假设我们定义左边为方向0,逆时针判断,此时,是一个死胡同,我们就要向后退一个。
具体的算法是这样:
有一个while循环,在路径栈不为空的时候,一直在循环:
do
{
if(若当前位置可通)
{
将当前位置插入栈顶
if(当前位置是出口位置)
结束
else
切换当且位置的第1方向方块位当前位置
}else
{
if(栈不为空&&栈顶位置尚有其他方向未探索)
去栈顶方块的下一个方向的相邻方块作为当前方块
else if(栈不为空&&其他位置皆不可通)
{
删去栈顶位置;
if(栈不为空)
重新测试新的栈顶位置,直到找到一个可通的相邻块或出栈至栈空;
}
}
}while(栈不为空)
下面是实现的代码:
/**
*stack.h
*/
#ifndef _STACK_H
#define _STACK_H
#include "data.h"
#define STACK_INIT_SIZE 10
#define STACK_INCREME 10
typedef struct
{
ElemType *base;
ElemType *top;
int size;
}STACK;
STACK * InitStack();
void DestroyStack(STACK *s);
int Push(STACK *s,ElemType *e);
int Pop(STACK *s,ElemType *e);
int IsEmpty(STACK *s);
#endif
/**
*data.h
*/
#ifndef _DATA_H
#define _DATA_H
//位置坐标结构
typedef struct
{
int x,y;
}POS;
//有效的路径结构
typedef struct
{
int sno;//路径编号
POS seat;//路径位置
int di;//该路径的方向
}ElemType;
#endif
/**
*stack.cpp
*/
#include "stack.h"
#include <iostream>
STACK * InitStack()
{
STACK * s = (STACK *)malloc(sizeof(STACK));
if(s == NULL)
exit(0);
s->base = (ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType));
if(s->base == NULL)
exit(0);
s->top = s->base;
s->size = STACK_INIT_SIZE;
return s;
}
void DestroyStack(STACK *s)
{
free(s->base);
free(s);
}
int Push(STACK *s,ElemType *e)
{
if(s==NULL||e==NULL)
return 0;
if(s->top - s->base >=s->size)
{
s->base = (ElemType *)realloc(s->base,
(s->size + STACK_INCREME)*sizeof(ElemType));
if(s->base == NULL)
return 0;
s->top = s->base + s->size;
s->size = s->size + STACK_INCREME;
}
*s->top = *e;
s->top ++;
return 1;
}
int Pop(STACK *s,ElemType *e)
{
if(s==NULL||e==NULL)
return 0;
if(s->base == s->top)
return 0;
*e = *(--s->top);
return 1;
}
int IsEmpty(STACK *s)
{
return s->top == s->base ?1:0;
}
/**
*main.cpp
*/
#include "stack.h"
#include "data.h"
#include <iostream>
#include <stdlib.h>
#include <conio.h>
using namespace std;
int item[10][10]=
{
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,0,0,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1}
};
static const POS inPos = {1,1}, outPos ={8,8};
int IsPass(POS curP)
{
return item[curP.y][curP.x]==0 ? 1:0;
}
POS NextPos(POS curP,int di)
{
//0,1,2,3
POS p = curP;
switch(di)
{
case 0:
p.x--;
break;
case 1:
p.y++;
break;
case 2:
p.x++;
break;
case 3:
p.y--;
}
return p;
}
void PrintItem(POS curP)
{
int i,j;
system("cls");
for(i = 0;i<10;i++)
{
for(j=0;j<10;j++)
{
if(i==curP.y&&j==curP.x)
{
cout<<"O";
continue;
}
if(item[i][j]==2)
cout<<"+";
else if (item[i][j] ==1)
cout<<"X";
else
cout<<" ";
}
cout<<endl;
}
}
int main()
{
ElemType e;
int step =1;
POS curPos = inPos;
STACK * s = InitStack();
PrintItem(inPos);
do
{
if(IsPass(curPos))
{
e.sno = step;
e.di = 0;
e.seat = curPos;
Push(s,&e);
item[curPos.y][curPos.x] = 2;
if(curPos.y == outPos.y && curPos.x == outPos.x)
{
PrintItem(curPos);
getch();
cout<<"OK"<<endl;
while(!IsEmpty(s))
{
ElemType r;
Pop(s,&r);
cout<<"("<<r.seat.x<<","<<r.seat.y<<")";
}
cout<<endl;
break;
}
PrintItem(curPos);
getch();
curPos = NextPos(curPos,0);
step++;
}
else
{
//先出栈(后面还会再进)获取当前路径元素
Pop(s,&e);
if(e.di==4 && !IsEmpty(s))
{
item[curPos.y][curPos.x]=3;
Pop(s,&e);
}
if(e.di <=3)
{
e.di ++;
Push(s,&e);
curPos = NextPos(e.seat,e.di);
}
}
}while(!IsEmpty(s));
return 0;
}
system("cls");是清除,引用了stdlib头文件
getch(); 是暂停,引用了conio头文件
运行效果如下:





浙公网安备 33010602011771号