数据结构--栈-C语言实现迷宫求解
数据结构–栈C语言实现迷宫求解
- 前言
代码主要根据《数据结构》(C语言版)严蔚敏提供的C语言伪代码而写,改变了其中的一些小细节。提供这个代码主要不是学习栈,而是学习穷举迷宫求解算法,另外代码中用到了二级指针,必须要对指针熟悉才行。
运行的时候可以改变00_stack_maze.h中的相关参数来改变迷宫的规模以及迷宫中障碍的数量,开始可以调得小一些。
程序是每隔两秒打印一次,程序中的方向用每个方向英文单词首字母表示。
另外推荐学习视频是B站的数据结构官方视频,最后如果觉得代码可读性很差或者有错误,轻点骂。 - 迷宫求解思想
迷宫求解主要思想是回溯法。
- 代码
00_state.h
*预定义常量和类型
*/#ifndef __00_STATE_H__
#define __00_STATE_H__#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<windows.h>#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2typedef int Status;#endif
/*
*02_stack_maze.h
*/#include"00_state.h"
#define SleepTime 2
#define MAZE_SIZE 7
#define OBSTACLE_NUMBER 10
#define STACK_INIT_SIZE 100//存储空间初始分配量
#define STACK_INCREMENT 10//存储空间分配增量typedef enum{ACCESSIBLE,START,END,OBSTACLE,MARKED,//走过的通道 NOT_ACCESSIBLE//走过但是退回来了
}maze[MAZE_SIZE][MAZE_SIZE],STATE;typedef enum{EAST,SOUTH,WEST,NORTH
}DIR;typedef struct{int X;int Y;
}PosType;typedef struct {int order; //通道序号PosType seat; //坐标DIR dir; //下一个该访问的方向
}maze_block,StackElemType;//迷宫通道类型,也是栈元素 typedef struct{StackElemType *base;StackElemType *top;int stacksize;//当前已经分配的存储空间
}stack;Status stack_init(stack * pstack);//构造空栈
StackElemType get_top(stack stack_,StackElemType *e);//获取栈顶元素
Status pop(stack *pstack,StackElemType *e);
StackElemType get_top(stack stack_,StackElemType *e);//获取栈顶元素
Status stack_empty(stack stack_);bool maze_path(maze maze_, PosType start, PosType end);
void create_maze(maze maze_);//构造一个迷宫
void print_maze(maze maze_);//打印迷宫
Status not_exist_in_stack(stack stack_,PosType pos);
Status pass(maze maze_,PosType pos,stack stack_);
void track_mark(maze maze_,PosType curpos);
STATE get_pos_state(maze maze_, PosType curpos);
PosType get_next_pos(maze maze_,PosType curpos,DIR dir);
void mark_not_accessible(maze maze_,PosType pos);
Status get_pos_dir_from_stack(stack stack_,int i,int j,DIR * dir);
/*
*02_stack_maze.cpp
*/
#include"02_stack_maze.h"
stack stack_;Status stack_init(stack * pstack)//构造空栈
{pstack->base = (StackElemType*)malloc(STACK_INIT_SIZE*sizeof(StackElemType));if(!pstack->base)exit(OVERFLOW);pstack->top = pstack->base;pstack->stacksize = STACK_INIT_SIZE;return OK;
}
StackElemType get_top(stack stack_,StackElemType *e)//获取栈顶元素
{if(stack_.top == stack_.base)exit(1);*e = *(stack_.top-1);return *e;
}Status push(stack *pstack,StackElemType e)
{if(pstack->top-pstack->base>=pstack->stacksize)//指针相减{pstack->base = (StackElemType*)realloc(pstack->base,(pstack->stacksize+STACK_INCREMENT)*sizeof(StackElemType));if(!pstack->base)exit(OVERFLOW);pstack->top=pstack->base+pstack->stacksize;pstack->stacksize+=STACK_INCREMENT;}*(pstack->top) = e;//先赋值,然后指针上移pstack->top++; return OK;
}Status pop(stack *pstack,StackElemType *e)
{if(pstack->top==pstack->base) {printf("栈为空\n");return ERROR;}else{pstack->top--;//先指针下移,然后赋值*e = *(pstack->top);return OK; }
}Status stack_empty(stack stack_)
{return stack_.base == stack_.top?TRUE:FALSE;
}void print_stack(stack stack_)
{StackElemType *base = stack_.base;StackElemType *top = stack_.top;while(base<top){printf("%d",base->dir);base++;}
}
Status not_exist_in_stack(stack stack_,PosType pos)//判断当前位置是否为已经走过的路径
{StackElemType *base = stack_.base;StackElemType *top = stack_.top;if(base == top)//栈为空,当前位置不在当前路径上 return TRUE; else{while(base<top){if(base->seat.X == pos.X&&base->seat.Y == pos.Y)return FALSE; elsebase++;}}return TRUE;
}
Status pass(maze maze_,PosType pos,stack stack_)//当前位置可以通过,即未曾走到过的通道块
{if ((maze_[pos.X][pos.Y] ==ACCESSIBLE ||maze_[pos.X][pos.Y] ==START||maze_[pos.X][pos.Y] ==END)&& not_exist_in_stack(stack_,pos)) return TRUE;
}void track_mark(maze maze_,PosType curpos)//标记当前位置为已经走过
{//if(maze_[curpos.X][curpos.Y] == END);maze_[curpos.X][curpos.Y] = MARKED;}STATE get_pos_state(maze maze_, PosType curpos)
{return maze_[curpos.X][curpos.Y];
}PosType get_next_pos(maze maze_,PosType curpos,DIR dir)
{PosType pos = curpos;switch(dir){case EAST:pos.Y++;break;case SOUTH:pos.X++;break;case WEST:pos.Y--;break;case NORTH:pos.X--;break;default:printf("切换方向错误\n");exit(1); }return pos;
}void mark_not_accessible(maze maze_,PosType pos)
{maze_[pos.X][pos.Y] = NOT_ACCESSIBLE;
}Status get_pos_dir_from_stack(stack stack_,int i,int j,DIR * dir)
{if(stack_empty(stack_)){return FALSE; }else{StackElemType *base = stack_.base;StackElemType *top = stack_.top;while(base<top){if(base->seat.X == i&&base->seat.Y == j){*dir = base->dir;break;}elsebase++;} }return FALSE;
}
bool maze_path(maze maze_, PosType start, PosType end)
{start.X = 1;start.Y = 1;PosType curpos = start;int curstep = 1;do{if(pass(maze_,curpos,stack_))//当前位置可以通过,即未曾走到过的通道块 ,纳入路径,继续前进 {if(get_pos_state(maze_,curpos) == END){printf("找到出口,坐标:(%d,%d)\n",curpos.X,curpos.Y);exit(0);}elsetrack_mark(maze_, curpos);StackElemType e;e.order = curstep;e.seat = curpos;e.dir = EAST;push(&stack_,e);
// if(get_pos_state(maze_,curpos) == END)
// return TRUE;curpos = get_next_pos(maze_,curpos,EAST);//当前位置通,不是出口 curstep++;// print_maze(maze_);}//if passelse//{if(!stack_empty(stack_)){StackElemType e;pop(&stack_,&e);curpos= e.seat;while(e.dir ==NORTH &&!stack_empty(stack_))//栈不空且栈顶位置的四周均不可通 {mark_not_accessible(maze_,e.seat);//标记当前位置不可通过pop(&stack_,&e); curpos = e.seat;}//while e.dirif(e.dir<NORTH )//换向探索 {e.dir = (DIR)(e.dir+1);push(&stack_,e);curpos = get_next_pos(maze_,curpos,e.dir);//设定当前位置是新方向上的相邻块 }//if e.dir }//if ! stack_empty}//else print_maze(maze_); }while(!stack_empty(stack_));return FALSE; }void create_maze(maze maze_)//迷宫为MAZE_SIZE*MAZE*SIZE,其中之间的(MAZE_SIZE-2)*(MAZE_SIZE-2)为迷宫主要部分,外面的一层作为墙壁
{int i = 0;int j = 0;for(;j<MAZE_SIZE;j++)//第一行和最后一行为墙 {maze_[0][j] = OBSTACLE;maze_[MAZE_SIZE-1][j] =OBSTACLE;}for(;i<MAZE_SIZE;i++)//第一列和最后一列为墙{maze_[i][0] = OBSTACLE;maze_[i][MAZE_SIZE-1] = OBSTACLE;}//srand(time(0));int k = 0;for(; k < OBSTACLE_NUMBER; k++){i = rand()%(MAZE_SIZE-2)+1;j = rand()%(MAZE_SIZE-2)+1;maze_[i][j] = OBSTACLE;}//固定起点maze_[1][1] = START;//固定终点maze_[MAZE_SIZE-2][1] = END;
}void print_maze(maze maze_)//打印迷宫 {int i = 0;int j = 0;for( i = 0; i<MAZE_SIZE; i++){for( j = 0; j<MAZE_SIZE;j++){switch(maze_[i][j]){case ACCESSIBLE: printf(" ");break;case MARKED:DIR dir;get_pos_dir_from_stack(stack_,i,j,&dir);switch(dir){case EAST:printf("%c",'E');break;case SOUTH:printf("%c",'S');break;case WEST:printf("%c",'W');break;case NORTH:printf("%c",'N');break;default:printf("error2");break;}break;case START:printf("?");break;case OBSTACLE:printf("#");break;case END:printf("!");break;case NOT_ACCESSIBLE:printf("$");break; default:printf("error");break; }// printf("%d",(int)maze_[i][j]);}printf("\n");}Sleep(2000);system("cls");}int main(void)
{stack_init(&stack_);maze maze_ = {ACCESSIBLE};create_maze(maze_);PosType start,end;start.X = 1;start.Y = 1;end.X = MAZE_SIZE-2;end.Y = 1;print_maze(maze_);maze_path(maze_,start,end);print_maze(maze_);//print_stack(stack_);return 0;
}
数据结构--栈-C语言实现迷宫求解相关推荐
- 《数据结构实践》设计报告---迷宫求解
<数据结构实践>设计报告-迷宫求解 因为学校要求答辩结课,给了很多题目都不太会,决定把感兴趣的都做一做,在这存档备用. 课程设计题目:迷宫求解 课程设计主要内容和要求: 一.设计目的: 1 ...
- c语言作业迷宫代码,用c语言实现迷宫求解完美源代码
<用c语言实现迷宫求解完美源代码>由会员分享,可在线阅读,更多相关<用c语言实现迷宫求解完美源代码(7页珍藏版)>请在人人文库网上搜索. 1.include #include ...
- 表达式求值(数据结构栈,c语言版)
表达式求值 一.实验题目 1.案例分析 2.案例实现 3.算法步骤 4.算法描述 二.工具环境 三.实验问题 四.实验代码 一.实验题目 1.案例分析 任何一个表达式都是由操作数(operand)运算 ...
- 数据结构——栈(C语言)
C语言实现栈 github代码下载 一. 栈的概念及结构 二.栈的实现 2.1 栈的存储定义 2.2 栈的初始化 2.3 入栈 2.4 出栈 2.5 获取栈顶元素 2.6 获取栈中有效元素个数 2.7 ...
- 数据结构-栈(C语言代码)
栈(stack)又名堆栈,它是一种运算受限的线性表.限定仅在表尾进行插入和删除操作的线性表.这一端被称为栈顶,相对地,把另一端称为栈底.向一个栈插入新元素又称作进栈.入栈或压栈,它是把新元素放到栈顶元 ...
- c语言迷宫问题输出坐标,C语言数据结构之迷宫求解问题
现在网上各种对于迷宫的求解,版本多的数不胜数.本人小白一枚,贴上自己对迷宫的求解这个小项目,自己写的.望能帮助一些同样有困难的人,毕竟我当时费解了好一会儿时间呢. 首先,先标明对于迷宫求解这个项目,首 ...
- c语言 栈结构存放数据类型,数据结构——栈的详解
栈和队列是两种重要的线性结构,从数据结构的角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表的子集.他们是操作受限的线性表,因此,可称为限定性的数据结构.但从数据类型角度看,他们是和线 ...
- 数据结构(C语言版) 第 三 章 栈与队列 知识梳理 + 作业习题详解
目录 一.栈 0.栈的基本概念 1.栈的实现 2.栈与递归 3.Hanoi塔问题 二.队列 0.队列的基本概念 1.队列的实现 2.循环队列 2.1循环队列的相关条件和公式: 3.链队列 4.链队列完 ...
- java使用链栈实现迷宫求解
java实现链栈在前面有所介绍:http://www.cnblogs.com/lixiaolun/p/4644141.html java实现链栈的代码: package stackapplicatio ...
- c++:栈的基本操作+实例:迷宫求解
栈的基本操作+实例:迷宫求解 #include<iostream> using namespace std;struct Node {int datai;int dataj;Node* n ...
最新文章
- 判断有向图g中顶点i到顶点j是否有路径_[源码和文档分享]基于Dijkstra算法的最短路径问题求解...
- cocos2d 中判断CGPoint或者CGSize是否相等
- shell实例第10讲:判断用户输入的是否为数字
- 在矩阵中查找字符串 Word Search
- 不用软件,手动修复双系统引导进win7,xp的多种方法
- [ZJOI2010] 排列计数(dp + 组合数)
- 出现特殊分隔符无法分隔解决方案
- 数据增长浪潮下,PCIe 6.0的问与Rambus的答
- 线程超时 php-fpm,php-fpm线程僵死导致网站无响应
- CSharpGL(53)漫反射辐照度
- birt预览能有内容发布后没内容_VS Code 1.52 发布!
- Kubernetes 小白学习笔记(29)--kubernetes云原生应用开发-基于Elasticsearch技术栈搭建Kubernetes的集群Logging设施
- Python + OpenCv实现视频中的车辆检测计数(车流量统计) (2020.7.15已更新源码)
- cad怎么表示出一个孔_AutoCAD如何画一个带孔的立体球
- B站收藏 6.1w+!GitHub 标星 3.9k+!这门神课拯救了我薄弱的计算机基础
- linux-centos7解决视频无法看问题(安装Adobe flash player)
- GIF 斗图警告!GitHub 标星 5.5k+,Sorry 会编程就是可以 为所欲为!
- 1_01_GLib库入门与实践_GLib库简介
- 洛谷P3387 【模板】缩点(tarjan)
- 物流快递系统程序设计