数据结构–栈C语言实现迷宫求解

  1. 前言
    代码主要根据《数据结构》(C语言版)严蔚敏提供的C语言伪代码而写,改变了其中的一些小细节。提供这个代码主要不是学习栈,而是学习穷举迷宫求解算法,另外代码中用到了二级指针,必须要对指针熟悉才行。
    运行的时候可以改变00_stack_maze.h中的相关参数来改变迷宫的规模以及迷宫中障碍的数量,开始可以调得小一些。
    程序是每隔两秒打印一次,程序中的方向用每个方向英文单词首字母表示。
    另外推荐学习视频是B站的数据结构官方视频,最后如果觉得代码可读性很差或者有错误,轻点骂。
  2. 迷宫求解思想
    迷宫求解主要思想是回溯法。

  1. 代码
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. 《数据结构实践》设计报告---迷宫求解

    <数据结构实践>设计报告-迷宫求解 因为学校要求答辩结课,给了很多题目都不太会,决定把感兴趣的都做一做,在这存档备用. 课程设计题目:迷宫求解 课程设计主要内容和要求: 一.设计目的: 1 ...

  2. c语言作业迷宫代码,用c语言实现迷宫求解完美源代码

    <用c语言实现迷宫求解完美源代码>由会员分享,可在线阅读,更多相关<用c语言实现迷宫求解完美源代码(7页珍藏版)>请在人人文库网上搜索. 1.include #include ...

  3. 表达式求值(数据结构栈,c语言版)

    表达式求值 一.实验题目 1.案例分析 2.案例实现 3.算法步骤 4.算法描述 二.工具环境 三.实验问题 四.实验代码 一.实验题目 1.案例分析 任何一个表达式都是由操作数(operand)运算 ...

  4. 数据结构——栈(C语言)

    C语言实现栈 github代码下载 一. 栈的概念及结构 二.栈的实现 2.1 栈的存储定义 2.2 栈的初始化 2.3 入栈 2.4 出栈 2.5 获取栈顶元素 2.6 获取栈中有效元素个数 2.7 ...

  5. 数据结构-栈(C语言代码)

    栈(stack)又名堆栈,它是一种运算受限的线性表.限定仅在表尾进行插入和删除操作的线性表.这一端被称为栈顶,相对地,把另一端称为栈底.向一个栈插入新元素又称作进栈.入栈或压栈,它是把新元素放到栈顶元 ...

  6. c语言迷宫问题输出坐标,C语言数据结构之迷宫求解问题

    现在网上各种对于迷宫的求解,版本多的数不胜数.本人小白一枚,贴上自己对迷宫的求解这个小项目,自己写的.望能帮助一些同样有困难的人,毕竟我当时费解了好一会儿时间呢. 首先,先标明对于迷宫求解这个项目,首 ...

  7. c语言 栈结构存放数据类型,数据结构——栈的详解

    栈和队列是两种重要的线性结构,从数据结构的角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表的子集.他们是操作受限的线性表,因此,可称为限定性的数据结构.但从数据类型角度看,他们是和线 ...

  8. 数据结构(C语言版) 第 三 章 栈与队列 知识梳理 + 作业习题详解

    目录 一.栈 0.栈的基本概念 1.栈的实现 2.栈与递归 3.Hanoi塔问题 二.队列 0.队列的基本概念 1.队列的实现 2.循环队列 2.1循环队列的相关条件和公式: 3.链队列 4.链队列完 ...

  9. java使用链栈实现迷宫求解

    java实现链栈在前面有所介绍:http://www.cnblogs.com/lixiaolun/p/4644141.html java实现链栈的代码: package stackapplicatio ...

  10. c++:栈的基本操作+实例:迷宫求解

    栈的基本操作+实例:迷宫求解 #include<iostream> using namespace std;struct Node {int datai;int dataj;Node* n ...

最新文章

  1. 判断有向图g中顶点i到顶点j是否有路径_[源码和文档分享]基于Dijkstra算法的最短路径问题求解...
  2. cocos2d 中判断CGPoint或者CGSize是否相等
  3. shell实例第10讲:判断用户输入的是否为数字
  4. 在矩阵中查找字符串 Word Search
  5. 不用软件,手动修复双系统引导进win7,xp的多种方法
  6. [ZJOI2010] 排列计数(dp + 组合数)
  7. 出现特殊分隔符无法分隔解决方案
  8. 数据增长浪潮下,PCIe 6.0的问与Rambus的答
  9. 线程超时 php-fpm,php-fpm线程僵死导致网站无响应
  10. CSharpGL(53)漫反射辐照度
  11. birt预览能有内容发布后没内容_VS Code 1.52 发布!
  12. Kubernetes 小白学习笔记(29)--kubernetes云原生应用开发-基于Elasticsearch技术栈搭建Kubernetes的集群Logging设施
  13. Python + OpenCv实现视频中的车辆检测计数(车流量统计) (2020.7.15已更新源码)
  14. cad怎么表示出一个孔_AutoCAD如何画一个带孔的立体球
  15. B站收藏 6.1w+!GitHub 标星 3.9k+!这门神课拯救了我薄弱的计算机基础
  16. linux-centos7解决视频无法看问题(安装Adobe flash player)
  17. GIF 斗图警告!GitHub 标星 5.5k+,Sorry 会编程就是可以 为所欲为!
  18. 1_01_GLib库入门与实践_GLib库简介
  19. 洛谷P3387 【模板】缩点(tarjan)
  20. 物流快递系统程序设计

热门文章

  1. 深入浅出 — 数据分析
  2. Redis视频教程免费下载
  3. testbench实例 vhdl_VHDL TestBench基础(转)
  4. 无软驱免F6在联想R510-G6-1U服务器上安装win 2003企业版的经历
  5. C# 制作一个定时关机小软件
  6. android 高音质 播放器,安卓音质最强音乐播放器—Rockbox
  7. B站韩顺平java学习笔记(九)-- 面向对象编程(高级)章节
  8. 恒生校招java笔试数据库语法_2015恒生电子校招笔试详解
  9. 深入浅出聊优化:从Draw Calls到GC(转)
  10. 剧透和评析之車輪の国、向日葵の少女