您的位置:首页 > 理论基础 > 数据结构算法

数据结构之迷宫求解 使用栈

2013-03-16 09:52 375 查看
// Maze.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "stdio.h"
#include "iostream"

using namespace std;

const int M=10;
const int N=10;
int maze[M]
=
{
1,1,1,1,1,1,1,1,1,1,
1,0,1,0,0,1,1,0,0,1,
1,0,0,1,0,0,0,0,0,1,
1,1,0,0,1,0,0,1,0,1,
1,0,0,1,0,0,0,0,1,1,
1,1,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,1,0,1,1,
1,1,1,1,0,1,0,0,0,1,
1,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1
}; // 定义迷宫

int next_xy[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; // 用于计算下一次搜索位置的计算量

typedef struct
{
int x;
int y;
}PosType; // 用于记录在迷宫中的位置

typedef struct
{
int ord;
PosType seat;
int di; // 记录方向
}SElemType;  // 栈的元素类型

typedef struct node
{
SElemType data;
struct node *link;
}LinkedNode;

int Init(LinkedNode *&top);
int Push(LinkedNode *&top, SElemType e);
int Pop(LinkedNode *&top,SElemType &e);
int GetTop(LinkedNode *&top, SElemType &e);
int StackEmpty(LinkedNode *&top);

int Pass(PosType e);
int FootPrint(PosType e);
PosType NextPos(PosType &e,int di);
int MarkPrint(PosType e);
int MazePath(int MAZE[M]
,PosType start,PosType end,LinkedNode *&stack);

// 定义一个全局的栈
LinkedNode *stack;

int _tmain(int argc, _TCHAR* argv[])
{
PosType start,end;
start.x=1;
start.y=1; // 起点
end.x=8;
end.y=8;   // 终点
// 初始化栈
Init(stack);
// 打印当前迷宫
for (int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
printf("%2d",maze[i][j]);
}
printf("\n");
}
printf("resolve the maze problem....\n");
MazePath(maze,start,end,stack); //调用迷宫求解函数
// 打印当前迷宫
for (int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
printf("%2d",maze[i][j]);
}
printf("\n");
}
printf("foot print\n");
SElemType e;
while(!StackEmpty(stack))
{
Pop(stack,e);
printf("%d,%d,%d",e.seat.x,e.seat.y,e.ord);
printf("\n");
}
system("pause");
return 0;
}

// 迷宫路径搜索,对全局栈的引用
int MazePath(int MAZE[M]
,PosType start,PosType end,LinkedNode *&stack)
{
//LinkedNode *stack;
//Init(stack); // 初始化栈
PosType currentPos;
SElemType e;
int curstep;

currentPos=start; // 开始位置
curstep=1;
do
{
if (Pass(currentPos)) // 如果当前结点可通,表示当前结点是第一次访问到
{
FootPrint(currentPos); //做访问标记
e.ord=curstep; // 搜索次数
e.seat.x=currentPos.x;
e.seat.y=currentPos.y; // 记录当前可通结点的情况
e.di=1; // 当前可通结点的访问方向为1,东南西北顺序访问
Push(stack,e); // 因为当前结点可通,所以将当前结点入栈,进一步判断当前结点的东南西北结点是否可通
// 同时,将当前结点入栈,防止下一步不可通的时候从当前结点获得下次可以访问的下个结点
if ((currentPos.x==end.x)&&(currentPos.y==end.y))
{
// 到了出口
return 1;
}
currentPos=NextPos(currentPos,1); // 当前点可通,访问当前点的第一个结点
curstep++; // 搜索次数加1
}
else
{
if (!StackEmpty(stack))
{
// 当前结点不可通,包括当前结点已经被修改了以后的情况
Pop(stack,e); // 回到上一个访问结点
while(e.di==4&&!StackEmpty(stack)) // 当前结点的所有下一步都访问过,且栈不为空,没有路可走,需要返回到上一步
{
MarkPrint(e.seat);
Pop(stack,e);
}
if (e.di<4)
{
// 还有其他的下一步没有访问到
e.di++;
Push(stack,e);
currentPos=NextPos(e.seat,e.di);
}
}
}
} while (!StackEmpty(stack)); // 栈不空,则继续寻找下一个可走的结点
return -1; // 当所有的栈元素出栈以后,栈为空,且没有返回找到的路径,那么说明已经没有其他的路可走,找不到通路
}
// 留下不能通过痕迹
int MarkPrint(PosType e)
{
int i,j;
i=e.x;
j=e.y;
maze[i][j]=1; //标记不能通过
return 1;
}

// 计算下一步的位置
PosType NextPos(PosType &e,int di)
{
e.x=e.x+next_xy[di-1][0];
e.y=e.y+next_xy[di-1][1];
return e;
}

// 判断当前点是否可通
int Pass(PosType e)
{
int i,j;
i=e.x;
j=e.y;
if(maze[i][j]==0)
{
// 0 表示当前路径可通
return 1;
}
return 0;
}

int FootPrint(PosType e)
{
int i,j;
i=e.x;
j=e.y;
maze[i][j]=3; //进行已经访问过标记, 用3表示此点已经访问过
return 1;
}

int Init(LinkedNode *&top)
{
top=(LinkedNode*)malloc(sizeof(LinkedNode));
if (!top)
{
return -1; // 初始化失败
}
top->link=NULL;
return 1;
}

int Push(LinkedNode *&top, SElemType e)
{
node *p=(LinkedNode*)malloc(sizeof(LinkedNode));
if (!p)
{
return -1;
}
p->data=e;
p->link=top->link;
top->link=p; // 在链表的头部插入新的结点,入栈
return 1;
}

int Pop(LinkedNode *&top,SElemType &e)
{
if (top->link==NULL)
{
return -1;
}
e=top->link->data;
node *p=top->link;
top->link=top->link->link;
free(p);
return 1;
}

int GetTop(LinkedNode *&top, SElemType &e)
{
if (top->link==NULL)
{
return -1;
}
e=top->link->data;
return 1;
}

// 判断栈是否为空
int StackEmpty(LinkedNode *&top)
{
if (top->link==NULL)
{
return 1;
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: