文章目录

  • 一.算法概述
    • 迷宫如下:
    • 1.初始化迷宫并输出
    • 2.用二维数组记录是否到过迷宫中的点
    • 3.定义(1,1,3)为起始点坐标
    • 4.算法核心:
    • 5.循环结束,栈中从底到顶即为一条路线
    • 6.输出所有的路线,并求出最短路线
  • 二.具体代码实现:
  • 三.实验截图:

一.算法概述

迷宫如下:

        0 1 2 3 4 5 6 7 8 90 1 1 1 1 1 1 1 1 1 11    1 0 1 1 1 0 1 1 1 12    1 1 0 1 0 1 1 1 1 13    1 0 1 0 0 0 0 0 1 14    1 0 1 1 1 0 1 1 1 15    1 1 0 0 1 1 0 0 0 16    1 0 1 1 0 0 1 1 0 17    1 1 1 1 1 1 1 1 1 1

迷宫为8*6方阵
方向由1-8分别为上,右上,右,右下,下,左下,左,左上

1.初始化迷宫并输出

初始化一个长度10,宽度8二维数组,之所以要把长度宽度都加2,是因为需要一圈围墙来判断迷宫是否出界,并输入迷宫(注:这里我定义横向为长,纵向为宽,注意,在定义二维数组一定要maze[宽+2][长+2],也就是先宽再长)

2.用二维数组记录是否到过迷宫中的点

定义一个二维数组flag[Width+2][Length+2]记录各个点是否到过,是为1,否为0

3.定义(1,1,3)为起始点坐标

将当前坐标,当前方向定义为(1,1,3),即坐标(1,1)方向向右将flag[1][1]标记为1,初始化一个栈,用于保存路径。定义next_x,next_y保存下一待定坐标,为什么是待定呢?因为不一定能够走到,x,y为当前坐标

4.算法核心:

当下一个点的坐标不是终点坐标时,就用while一直循环遍历
即如果(next_x,next_y)不是(Length,Width),则一直循环
4.1.在进入方向循环之前,进行一次下一步待定坐标的求取
4.2.按照方向direction从1到8循环
4.2.1.求取下一步的待定坐标
4.2.2.判断这个待定坐标,如果下个点没来过(flag为0),并且下个点可以通行(maze为0)执行
{记录下来目前这个点的三个属性并将其压栈,沿着这个方向移动一次,
新到的点标记为来过(flag[y][x]=1)}
4.3.如果4.2.2中没有发生移动,证明走到了死角,保存走到死角之前的坐标,并将这个方向+1,再从这个新的坐标(走到死角之前的x,y坐标和这个+1后的方向)开始继续探索,然后把这个死角前坐标出栈
4.4.如果栈为空,那么迷宫无法出去

5.循环结束,栈中从底到顶即为一条路线

6.输出所有的路线,并求出最短路线

二.具体代码实现:

#include<iostream>
using namespace std;
void intend_move(int x,int y,int &next_x,int &next_y,int direction);//这个是修改下一步待定坐标的函数
void move(int &x,int &y,int &direction);//这个是修改当前坐标的函数
//链栈 注:由于不知道有多少个元素,所以用链栈可以省空间
template<class DataType>
struct Node
{DataType data;Node<DataType> *next;
};
template<class DataType>
class LinkStack
{public:LinkStack(){top=NULL;num=0;}~LinkStack(){};void Push(DataType x);DataType Pop();DataType GetTop(){if(top!=NULL)return top->data;}int Empty();int num;
private:Node<DataType> *top;
};
template<class DataType>//链栈入栈算法
void LinkStack<DataType>::Push(DataType x)
{Node<DataType> *s;s=new Node<DataType>;s->data=x;s->next=top;top=s;num++;
}
template<class DataType>//链栈出栈算法
DataType LinkStack<DataType>::Pop()
{Node<DataType> *p;p=new Node<DataType>;if(top==NULL)throw"下溢";DataType x=top->data;p=top;top=top->next;num--;delete p;return x;
}
template<class DataType>//判空操作
int LinkStack<DataType>::Empty()
{if(top==NULL)return 1;elsereturn 0;
}struct route
{int x;int y;int direction;
};
const int Length=8;
const int Width=6;
int main()
{/*      0 1 2 3 4 5 6 7 8 90    1 1 1 1 1 1 1 1 1 11    1 0 1 1 1 0 1 1 1 12    1 1 0 1 0 1 1 1 1 13    1 0 1 0 0 0 0 0 1 14    1 0 1 1 1 0 1 1 1 15    1 1 0 0 1 1 0 0 0 16    1 0 1 1 0 0 1 1 0 17    1 1 1 1 1 1 1 1 1 1//检验迷宫如图所示,0代表能通行,1代表不能通行,起点为maze[1][1],终点为maze[Width][Length]*/int i,j;bool maze[Width+2][Length+2]={{1,1,1,1,1,1,1,1,1,1},{1,0,0,1,1,0,0,1,1,1},{1,1,0,1,0,1,1,1,1,1},{1,0,1,0,0,0,0,0,1,1},{1,0,1,1,1,0,1,1,1,1},{1,1,0,0,1,1,0,0,0,1},{1,0,1,1,0,0,1,1,0,1},{1,1,1,1,1,1,1,1,1,1}};//初始化一个长度10,宽度8的二维数组,之所以要把长度宽度都加2,是因为需要一圈围墙来判断迷宫是否出界,并输入迷宫//注:这里我定义横向为长,纵向为宽,注意,在定义二维数组一定要maze[宽+2][长+2],也就是先宽再长cout<<"迷宫为:"<<endl;for(i=0;i<Width+2;i++){for(j=0;j<Length+2;j++)cout<<maze[i][j]<<" ";cout<<endl;}//输出迷宫bool flag[Width+2][Length+2]={0};//这个二维数组记录各个点是否到过,是为1,否为0//以下是求取路径算法LinkStack<route> Route;int x=1,y=1;int direction=1;//当前的坐标,当前的方向int next_x,next_y;//定义了下一步所走的点,如果x是横向的坐标,y是纵向的坐标,那么对应的点应该是maze[y][x]!!!这一点尤其注意,下面的同理,也需要这样表示int out_able=1;//设置标志,如果栈为空了,就把其置零,表明无法走出迷宫,否则说明走出了while循环且到达了目的地route NowNode;NowNode.x=1;NowNode.y=1;NowNode.direction=3;//起点,对应的是(1,1,右)flag[1][1]=1;//起点标记为来过cout<<"老鼠探索迷宫的路线为:"<<endl;while(next_x!=Length||next_y!=Width)//如果下一个坐标不是(8,6),这里要用到逻辑推理,A:x=8,B:y=6,出去的条件是AB,//那么 ′(AB)=′A U ′B,即next_x!=Length||next_y!=Width{int move_flag=0;//定义是否移动了,0为否,1为是for(direction=1;direction<=8;direction++)//按照方向direction从1到8循环{intend_move(x,y,next_x,next_y,direction);if(!flag[next_y][next_x]&&!maze[next_y][next_x])//如果下个点没来过(flag为0),并且下个点可以通行(maze为0)           {   NowNode.x=x;NowNode.y=y;NowNode.direction=direction;//记录下来目前这个点的三个属性Route.Push(NowNode);//把这个点压栈cout<<"("<<x<<","<<y<<","<<direction<<")\t";move(x,y,direction);//沿着这个方向移动一次flag[y][x]=1;//新到的点标记为来过move_flag=1;break;           }}if(!move_flag)//如果没有移动过,即move_flag=0,说明此路不通,把路线倒回去一个,即出栈一个元素,再走{cout<<"("<<x<<","<<y<<","<<0<<")\t";//输出死角坐标(死角坐标是当前的x,y值,并未压入栈)cout<<"("<<Route.GetTop().x<<","<<Route.GetTop().y<<","<<0<<")\t";//输出回退一个的坐标x=Route.GetTop().x;y=Route.GetTop().y;direction=Route.GetTop().direction+1;//Route.Pop();//要尤其注意这里的理解,走到死角之前的一个坐标方向是错的,所以这个点一定要出栈,但是在上一步中,我们已经保存了走到死角之前的那个坐标,所以就从死角前坐标的下一个方向再开始探索}if(Route.Empty()){cout<<"迷宫无法出去"<<endl;out_able=0;break;}}if(out_able)cout<<"终点(8,6,0)"<<endl;int t=0,num=Route.num;route *FinalRoute=new route[Route.num];for(;t<num;t++)FinalRoute[t]=Route.Pop();cout<<"一条路径为:";for(t=num-1;t>=0;t--)cout<<"("<<FinalRoute[t].x<<","<<FinalRoute[t].y<<","<<FinalRoute[t].direction<<")"<<" ";cout<<"终点(8,6,0)"<<endl;cout<<endl;return 0;
}//这个函数是用来计算下一个的坐标
void intend_move(int x,int y,int &next_x,int &next_y,int direction)//1,2,3,4,5,6,7,8所对应的是8个方向,从上、右上、右……左上分别对应1,2,3,4,5,6,7,8
{switch(direction){case 1:next_x=x;next_y=y-1;break;case 2:next_x=x+1;next_y=y-1;break;    case 3:next_x=x+1;next_y=y;break;case 4:next_x=x+1;next_y=y+1;break;case 5:next_x=x;next_y=y+1;break;case 6:next_x=x-1;next_y=y+1;break;case 7:next_x=x-1;next_y=y;break;case 8:next_x=x-1;next_y=y-1;break;}
}
void move(int &x,int &y,int &direction)
{switch(direction){case 1:x=x;y=y-1;break;case 2:x=x+1;y=y-1;break;    case 3:x=x+1;y=y;break;case 4:x=x+1;y=y+1;break;case 5:x=x;y=y+1;break;case 6:x=x-1;y=y+1;break;case 7:x=x-1;y=y;break;case 8:x=x-1;y=y-1;break;}direction=1;//移动后恢复坐标
}

三.实验截图:

数据结构——详解栈应用之迷宫问题相关推荐

  1. 万字长文的Redis五种数据结构详解(理论+实战),建议收藏。

    本文脑图 前言 Redis是基于c语言编写的开源非关系型内存数据库,可以用作数据库.缓存.消息中间件,这么优秀的东西一定要一点一点的吃透它. 关于Redis的文章之前也写过三篇,阅读量和读者的反映都还 ...

  2. redis数据结构详解之Hash(四)

    原文:redis数据结构详解之Hash(四) 序言 Hash数据结构累似c#中的dictionary,大家对数组应该比较了解,数组是通过索引快速定位到指定元素的,无论是访问数组的第一个元素还是最后一个 ...

  3. Python中的高级数据结构详解

    这篇文章主要介绍了Python中的高级数据结构详解,本文讲解了Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint这些数据结构的用法,需要的朋友可以参考 ...

  4. [转]Redis内部数据结构详解-sds

    本文是<Redis内部数据结构详解>系列的第二篇,讲述Redis中使用最多的一个基础数据结构:sds. 不管在哪门编程语言当中,字符串都几乎是使用最多的数据结构.sds正是在Redis中被 ...

  5. Redis数据结构详解之Zset(五)

    原文:Redis数据结构详解之Zset(五) 序言 Zset跟Set之间可以有并集运算,因为他们存储的数据字符串集合,不能有一样的成员出现在一个zset中,但是为什么有了set还要有zset呢?zse ...

  6. 【肝帝一周总结:全网最全最细】☀️Mysql 索引数据结构详解与索引优化☀️《❤️记得收藏❤️》

    [肝帝一周总结:全网最全最细]☀️Mysql 索引数据结构详解与索引优化☀️<❤️记得收藏❤️> 目录

  7. [redis] 10 种数据结构详解

    [redis] 10 种数据结构详解 简介 5种常见数据结构 string: 最常见的 string key value list: 双向链表 set: 集合- zset: 有序集合 hash: 类似 ...

  8. 数据结构详解——最大(小)左倾树

    数据结构详解--最大(小)左倾树 文章目录 数据结构详解--最大(小)左倾树 最大(小)左倾树的定义及用途 操作最大HBLT 合并操作 插入操作和删除操作 初始化操作 Java语言实现的最大HBLT ...

  9. 探索Redis设计与实现6:Redis内部数据结构详解——skiplist

    Redis内部数据结构详解(6)--skiplist  2016-10-05 本文是<Redis内部数据结构详解>系列的第六篇.在本文中,我们围绕一个Redis的内部数据结构--skipl ...

最新文章

  1. CCF201612-3 权限查询(100分)
  2. 网易云信稳定背后的秘密
  3. 容器+AOP实现动态部署(四)
  4. 平面设计完全手册_平面设计师的三大软件:PS、AI、ID该如何选择?| 平面设计纯干货...
  5. 数学魔鬼表达式——第一天
  6. 别人都不知道的“好用”网站,让你的效率飞快
  7. android 多渠道覆盖,Android多渠道包
  8. 深入解析SpringBoot启动原理
  9. AutoCAD 2004-2022 官方简体中文版下载直链
  10. 什么是 DOM 和 BOM?
  11. 卡卡又一次双手举天,巴西涉险过关,克罗地亚虽败尤荣.
  12. 程序员有前途吗?出路在哪里?
  13. ICP互联网信息服务(仅限互联网信息服务)
  14. oracle 主要特点是,Oracle PL/sql 主要特点
  15. matlab转差频率控制,异步电动机转差频率间接矢量控制matlab仿真(毕业设计).doc
  16. Shell学习总结-流编辑器sed
  17. 微博将于今日晚间挂牌上市 最高融资金额4.37亿美元
  18. fiddler安装和使用
  19. 影像信息提取之—— 监督与非监督分类
  20. 车间追溯系统有什么作用?

热门文章

  1. (边写边更)用PHP简单的学生个人信息记录程序
  2. 强化学习(一)模型基础
  3. jsp 单行注释多行注释_eclipse 中的注释 快捷键 多行注释快捷键 单行注释快捷键...
  4. urovo android sdk,Urovo-Android-4.0-SDK-扩展部分说明.pdf
  5. 2022,软件测试出路在哪里?
  6. 计算机上装的word怎么卸载,电脑残留Office无法重新安装如何解决|电脑完全卸载Office的方法...
  7. (不入流的排序算法)------猴子排序
  8. iOS开发-实现微博动态Demo展示
  9. 视频教程-自然语言处理--词向量视频教学(word embedding)-NLP
  10. AH8651,220V降转5V3.3V,无电感设计方案