C/C++迷宫问题详情分析--栈的应用
Posted CoutCodes
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C/C++迷宫问题详情分析--栈的应用相关的知识,希望对你有一定的参考价值。
文章目录
引言
这是一个简单的顺序栈的应用求解迷宫问题,主要分享的是在求解这个问题的之前的准备,
分析所需的数据,获得正确的数据结构,分析所需要的功能,划分模块,再分析各模块中,需要的具体功能,以确定功能函数。
这样也书写代码时,就可以事半功倍。
一,问题描述
迷宫求解问题
提出以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。迷宮问题要求,求出从入口(x,y)到出口(x,y)的一条通路,或得出没有通路的结论。
基本要求:首先实现一个以链表作存储结构的栈类型,然后编写一个求迷宫问题的非递归程序,求得的通路。
要求用栈实现迷宫问题的求解
将要构建的迷宫:向下为x正方向;向右为y正方向
二,分析所用数据结构
迷宫结构体用于存储构建的迷宫数据。
坐标结构体和栈元素结构体都是服务于栈结构体。
三、所需函数及其功能
这幅图可以很清晰的,了解都有哪些函数,这些函数的功能又是什么。
图中很多函数都是为了一个函数服务的,即求解迷宫的函数。
蓝色底的函数,实现了但是没有测试,大家可以自行测试
四、程序执行详细框图
这是整个迷宫问题项目的详细执行过程。大家可以先看看,到时候阅读代码也会更加清洗直观。
不同的颜色,是一个不同的模块,实现相应的功能
五、代码实现-详细注释
代码相应的地方都有注释,也体现了我思考的过程,如有错误或者更优解,欢迎在指正讨论。
1、maze.h
#ifndef __MAZE_H__
#define __MAZE_H__
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define TRUE 1
#define FALSE 0
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define COLUMN 10 //列
#define ROW 10 //行
typedef struct
char** maze; //迷宫二维数组
int** footprint; //足迹二维数组
int row;
int column;
MazeType;
typedef struct
int x;
int y;
PosType;
typedef struct
int ord; //通道块在路径上的序号
PosType seat; //通道块在迷宫中的“坐标位置”
int di; //从此通道块走向下一个通道块的“方向”
SElemType;
typedef struct
SElemType* base;
SElemType* top;
int stacksize;
SqStack;
//构造一个空栈
bool InitStack(SqStack* S);
//初始化迷宫数据
bool InitMaze(MazeType* M);
//判断是否为空栈
bool IsStackEmpty(SqStack S);
//入栈,元素e为新的栈顶元素,传入e形参拷贝值,返回改变的栈S,及是否入栈成功
bool Push(SqStack* S, SElemType e);
//出栈,指针传入地址,直接改变e变量,即返回改变的e和栈S,及是否出栈成功
bool Pop(SqStack* S, SElemType* e);
//输出迷宫
bool PrintfMaze(MazeType* M);
//输出迷宫的路径
bool PrintfFoot(MazeType* M, SqStack* S);
//将迷宫的当前位置Pos设置为“走过”,即footprint该位置为1
bool FootPrint(MazeType* M, PosType pos);
//判断当前位置是否走过
bool Pass(MazeType* M, PosType pos);
//创建新的节点,用step,pos,d初始化该点
SElemType NewSElemType(int step, PosType pos, int d);
//将位置pos的方向设为d
PosType NextPos(PosType pos, int d);
//若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底到栈顶)
bool MazePath(SqStack* S, MazeType maze, PosType start, PosType end);
//清空栈
bool ClearStack(SqStack* S);
//从栈底到栈顶依次对每个元素进行访问
bool StackTravel(const SqStack* S);
//返回栈的长度,即S元素的个数
int StackLength(SqStack S);
//若栈不为空,则用e返回S的栈顶元素
bool GetTop(SqStack S, SElemType* e);
#endif
2、maze.c
#include "maze.h"
//构造一个空栈
bool InitStack(SqStack* S)
//100*SElemType
S->base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!S->base)
printf("申请空间失败,迷宫无法初始化.\\n");
return false;
S->top = S->base;
S->stacksize = STACK_INIT_SIZE;
return true;
//初始化迷宫数据
bool InitMaze(MazeType* M)
char mz[ROW][COLUMN]=
'#',' ','#','#','#','#','#','#','#','#',
'#',' ',' ','#',' ',' ',' ','#',' ','#',
'#',' ',' ','#',' ',' ',' ','#',' ','#',
'#',' ',' ',' ',' ','#','#',' ',' ','#',
'#',' ','#','#','#',' ',' ',' ',' ','#',
'#',' ',' ',' ','#',' ','#',' ','#','#',
'#',' ','#',' ',' ',' ','#',' ',' ','#',
'#',' ','#','#','#',' ','#','#',' ','#',
'#','#',' ',' ',' ',' ',' ',' ',' ',' ',
'#','#','#','#','#','#','#','#','#','#',
;
M->maze = (char **)malloc(sizeof(char*)*ROW); //相当于分配一维数组空间,10个char*变量空间
M->footprint = (int **)malloc(sizeof(int*)*ROW); //相当于分配一维数组空间,10个int*变量空间
if(!M->maze || !M->footprint)
printf("申请空间失败,迷宫无法初始化.\\n");
return false;
for(int i = 0; i < ROW; i++)
M->maze[i]=(char*)malloc(sizeof(char)*COLUMN); //相当于分配二维数组空间,每个个char*指向,10个char大小变量空间
M->footprint[i]=(int*)malloc(sizeof(int)*COLUMN); //相当于分配二维数组空间,每个个int*指向,10个int大小变量空间
if(!M->maze[i] || !M->footprint[i])
printf("申请空间失败,迷宫无法初始化.\\n");
return false;
for(int i = 0; i <ROW; i++)
for(int j = 0; j < COLUMN; j++)
M->maze[i][j] = mz[i][j];
M->footprint[i][j] = 0;
M->row = ROW;
M->column = COLUMN;
return true;
//判断是否为空账
bool IsStackEmpty(SqStack S)
if(S.top == S.base)
return true;
else
return false;
//入栈,元素e为新的栈顶元素,传入e形参拷贝值,返回改变的栈S,及是否入栈成功
bool Push(SqStack* S, SElemType e)
//结构体类型,按单位大小相减类比int型,每个int型为4byte,相减2-1也是按斯单位相减
if(S->top - S->base >= S->stacksize) //如果超出本来的长度,进行动态的添加,每一次添加10个SElemType大小空间,STACKINCREMENT=10
S->base = (SElemType*)realloc(S->base,(S->stacksize + STACKINCREMENT)*sizeof(SElemType));
if(!S->base);
printf("重新申请空间失败.\\n");
return false;
S->top = S->base + S->stacksize; //栈顶指针指向原先栈的尾部,栈底+栈长度
S->stacksize +=STACKINCREMENT; //栈的长度+10
*S->top++=e; //栈顶指针+1前进,并且e赋值给解引用的指针,入栈
//后置++/--为第一优先级,*和前置++/--为第二优先级
return true;
//出栈,指针传入地址,直接改变e变量,即返回改变的e和栈S,及是否出栈成功
bool Pop(SqStack* S, SElemType* e)
if(S->top == S->base)
printf("栈为空.\\n");
return false;
*e = *(--S->top); //栈顶指针-1返回,并且解引用赋值给e
return true;
//输出迷宫
bool PrintfMaze(MazeType* M)
printf("%s","xy");
for(int i=0;i<M->column;i++)
printf("%d",i);
printf("\\n");
for(int i=0; i<M->row; i++)
printf("%d ",i);
for(int j=0; j<M->column; j++)
printf("%c",M->maze[i][j]);
printf("\\n");
printf("\\n");
//footprintf
printf("%s","xy");
for(int i=0;i<M->column;i++)
printf("%d",i);
printf("\\n");
for(int i=0; i<M->row; i++)
printf("%d ",i);
for(int j=0; j<M->column; j++)
printf("%d",M->footprint[i][j]);
printf("\\n");
printf("\\n");
return true;
//输出迷宫路径
bool PrintfFoot(MazeType* M, SqStack* S)
SElemType* p;
for(int i=0; i<M->row; i++) //将footprint置0
for(int j=0; j<M->column; j++)
M->footprint[i][j]=0;
p = S->base;
if(S->base == S->top)
printf("栈为空.\\n");
return false;
while(p != S->top) //根据栈中存有的节点的坐标,对footprint进行1路径赋值
M->footprint[p->seat.x][p->seat.y] = 1;
*p++;
for(int i=0; i<M->row; i++) //输出路径
for(int j=0; j<M->column; j++)
printf("%d",M->footprint[i][j]);
printf("\\n");
return true;
//将迷宫的当前位置Pos设置为“走过”,即footprint该位置为1
bool FootPrint(MazeType* M, PosType pos) //FootPrint足迹
if((pos.x>M->row) || (pos.y>M->column))
printf("坐标越界.\\n");
return false;
M->footprint[pos.x][pos.y]=1;
return true;
//判断当前位置是否走过
bool Pass(MazeType* M, PosType pos)
if((pos.x > M->row) || (pos.y > M->column))
printf("坐标越界.\\n");
return false;
if((0 == M->footprint[pos.x][pos.y])&&(M->maze[pos.x][pos.y]==' '))
return true; //通路没走过
else
return false; //通路走过或者墙
//创建新的节点,用step,pos,d初始化该点
SElemType NewSElemType(int step, PosType pos, int d)
SElemType e;
e.ord = step;
e.seat = pos;
e.di = d;
return e;
//将位置pos的方向设为d
PosType NextPos(PosType pos, int d)
switch(d)
case 1: //向下
pos.x++;
break;
case 2: //向右
pos.y++;
break;
case 3: //向上
pos.x--;
break;
case 4: //向左
pos.y--;
break;
default:
printf("error.\\n");
return pos;
//若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底到栈顶)
bool MazePath(SqStack* S, MazeType maze, PosType start, PosType end)
int curstep = 1;
SElemType e;
PosType curpos = start;
InitStack(S);
do
if(true == Pass(&maze, curpos)) //通路没走过
FootPrint(&maze,curpos);将当前点标记为走过
e=NewSElemType(curstep,curpos,1);//创建栈元素,将当前点的信息存储,便于出入栈及改变当前点的di信息
Push(S,e);
if((curpos.x==end.x)&&(curpos.y==end.y))//终点
printf("迷宫路径:\\n");
PrintfFoot(&maze,S);//打印通路路径
return true;
curpos 数据结构实验二 栈的应用——迷宫求解问题(c++版本)