顺序栈的实现----数据结构

栈的概念

对于栈(Stack),后进先出(Last In First Out,LIFO),栈也是一种线性表,只不过是一种操作受限的线性表,只能在一端操作,也就是不允许在中间进行查找、插入、删除等操作。

栈的图:

进出的一端称为栈顶(top),另一端称为栈底(base),栈可以顺序存储,也可以链式存储,这里讲的是栈的顺序存储方式。

栈也可以比喻成一个乒乓球桶,桶底是封口的,桶顶是打开的,桶的横截面积恰好为一个乒乓球投影的面积,也就是说你只能从最后一个乒乓球后放入乒乓球(后面放进去的乒乓球会压着前面的乒乓球),只能拿走最后一个乒乓球(不能拿走被压着的乒乓球)。

栈的算法实现

栈的数据定义

#define MAX_SIZE 120    //栈的最大容量
typedef int DateElem;
typedef struct _Stack
{DateElem* top;     //栈顶指针DateElem* base;    //栈底指针,指向栈的开始
}Stack;

初始化栈

bool initStack(Stack& s)
{s.base = new DateElem[MAX_SIZE];if (!s.base) return false;        //空间分配失败s.top = s.base;        //为空栈,栈中无任何元素return true;
}

销毁栈

销毁与初始化一一对应,初始化时申请了内存,销毁时就需要释放。

void destoryStack(Stack& s)
{if (s.base != NULL) //栈空间有效{delete s.base;s.base = s.top = NULL;}}

入栈

bool pushStack(Stack& s, DateElem e)
{if (!s.base || (s.top - s.base) >= MAX_SIZE) return false; //栈没建立 或者 栈空间满了*(s.top++) = e; //因为最开始 s->top = 0 return true;
}

出栈

bool popStack(Stack& s, DateElem& e) //用 e 返回被删除的元素的指
{if (!s.base || s.base == s.top) return false;e = *(--s.top); //先将栈顶元素赋值给e,栈顶指针再移动,因为栈顶指针都是指向栈顶元素的后一个位置,除了栈为空时,栈顶指针为 0return true;
}

获取栈顶元素

bool getTop(Stack& s,DateElem &e)
{if (s.top > s.base) //栈不为空{e = *(s.top - 1); //e 返回栈顶元素的值return true;}else{return false;}
}

判断栈是否为空

bool IsEmpty(Stack& s)
{if (s.base == s.top){	return true;}else{return false;}
}

获取栈中元素的个数

int getLength(Stack& s)
{return (int)(s.top - s.base);
}

栈的应用

迷宫问题

在给定区域内(二维数组)告诉你起点,找到一条到出口的移动路线。

迷宫求解问题

对于走出一个迷宫,我们只需要将所有的路都走一遍就可以走出迷宫(需要避免走重复的路,对走过的路做好标记),在这个过程中,如果遇到岔路,就选择其中一条路前进,如果碰到死胡同就返回,回退到上个岔路,选择别的路,如果这个岔路也无路可走了,继续回退到上个岔路选择一条路……直到找到出口,或者是无路可走。(我们把一个坐标的位置看作一个岔路,可以向上、下,左、右走

找迷宫的通路使用到的是回溯法,穷举法的改进,回溯的过程需要用到栈。(我最开始想到的是栈的递归)

回溯法:对一个包括有很多个结点,每个结点有若千个搜索分支的问题,把原问题分解为若千个子问题求解的算法;当搜索到某个结点发现无法再继续搜索下去时,就让搜索过程回溯(回退)到该节点的前一一个结点,继续搜索该节点外的其他尚未搜索的分支;如果发现该结点无法再搜索下去,就让搜索过程回溯到这个结点的前一结点继续这样的搜索过程;这样的搜索过程--直进行到搜索到问题的解或者搜索完了全部可搜索分支没有解存在为止。

代码实现 

其中栈存储的数据为,而不是之前的 int 类型了:

typedef struct _Position
{int x;int y;
}position;typedef position DateElem;

然后代码我就没有发关于顺序栈的实现了。

具体思想:

、在当前位置,分别判断左、上、右、下四个方向的位置是否为路。

、选择一条路,然后这条路就是当前位置了。(每当某个位置变为当前位置就要标记一下,入口也要,防止重复走),判断当前位置是否为终点,不为的话,执行步骤一。

、如果在当前位置,左、上、右、下四个方向的位置都走过了或者是墙,就回退到上一个位置(存储在栈中),执行步骤一、二。

、重复步骤一、二、三,直到找到出口或者回退到入口。

#include <iostream>
#include "顺序栈.h"using namespace std;#define ROW 6
#define COL 6typedef struct _Maze //迷宫的结构体
{int map[ROW][COL];
}Maze;void initMaze(Maze* maze, int map[ROW][COL]) //将传入的地图数据来初始化迷宫
{for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++){maze->map[i][j] = map[i][j];}}
}
void printMaze(Maze* maze) //打印整个迷宫
{for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++){cout << maze->map[i][j] << " ";}cout << endl;}
}int IsValidEnter(position* enter,Maze *maze) //判断入口是否有效
{if (!enter || !maze) return -1; //合法性检查if ((enter->x == 0 || enter->x == ROW-1 ) ||(enter->y == 0 || enter->y == COL-1) &&maze->map[enter->x][enter->y] == 1) //在地图的边界上并且是通路{return 1;}else{return 0;}
}
int IsValidExit(position *cur, Maze* maze,position *enter) //判断出口是否有效
{if (!cur || !maze || !enter) return -1; //合法性检查if (((cur->x == 0 || cur->x == ROW - 1) ||(cur->y == 0 || cur->y == COL - 1)) &&(enter->x != cur->x && enter->y != cur->y)) //在地图边界上,并且不是入口,那就是出口{return 1;}else{return 0;}}
int IsNextPass(position *next, Maze* maze) //判断下一步的位置是否有效
{if (!next || !maze) return -1; //合法性检查if ((next->x >= 0 && next->x < ROW) &&(next->y >= 0 && next->y < COL) &&maze->map[next->x][next->y] == 1) //在地图里,并且是路(没走过),等于2、3、4……就是走过的路{return 1;}else{return 0;}
}
int PassMaze(position *enter,Maze *maze,Stack *s)
{if (!maze || IsValidEnter(enter,maze) == 0) return 0; //迷宫为空或者入口无效position cur = { enter->x,enter->y }; //当前人所在的位置position next; // 保存下一步的位置pushStack(*s, cur); //入口入栈maze->map[enter->x][enter->y] = 2; // 走过的地方要改变他的值,防止重复走while (!IsEmpty(*s)){getTop(*s,cur); //得到当前所在的位置if (IsValidExit(&cur, maze, enter)) //是出口,就可以结束了{return 1;}next = cur;next.y--;    //尝试向左走一步,看看能不能继续走if (IsNextPass(&next, maze) == 1) {pushStack(*s, next); //下一步入栈maze->map[next.x][next.y] = maze->map[cur.x][cur.y] + 1; //下一步的值为当前位置的值+1continue;}next = cur;next.x--; //尝试向上走一步,看看能不能继续走if (IsNextPass(&next, maze) == 1){pushStack(*s, next);maze->map[next.x][next.y] = maze->map[cur.x][cur.y] + 1;continue;}next = cur;next.y++; //尝试向右走一步,看看能不能继续走if (IsNextPass(&next, maze) == 1){pushStack(*s, next);maze->map[next.x][next.y] = maze->map[cur.x][cur.y] + 1;continue;}next = cur;next.x++; //尝试向下走一步,看看能不能继续走if (IsNextPass(&next, maze) == 1){pushStack(*s, next); maze->map[next.x][next.y] = maze->map[cur.x][cur.y] + 1; continue;}//走到这里了,说明当前位置的四个方向都走不通,进行回溯(到上个结点),看看上个结点未被遍历的方向能否走通position temp;popStack(*s, temp);}return false;
}
int main(void)
{int map[ROW][COL] = {0,0,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,1,0,1,0,0,0,0,0,1,0}; // 二维数组代表迷宫,1代表路,0代表墙Maze maze;		//迷宫的拷贝initMaze(&maze, map);		//初始化maze迷宫//printMaze(&maze);		//打印迷宫,测试position enter = { 0,2 };		//创建了迷宫入口并初始化Stack s;		//栈用来保存已走过的路,便于回溯initStack(s);		//初始化栈if (PassMaze(&enter, &maze, &s)){cout << "恭喜你,找到了出口" << endl;}else{cout << "无路可走了" << endl;}printMaze(&maze); //打印迷宫return 0;
}

代码很多,但是结构清楚。以下是代码的执行效果,能清楚知道移动的轨迹。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/116794.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为云全新上线Serverless应用中心,支持一键构建文生图应用

近日&#xff0c;华为云全新上线Serverless应用中心&#xff0c;提供了大量应用模板&#xff0c;让用户能够一键部署函数和周边依赖资源&#xff0c;节省部署时间&#xff0c;快速上手将应用部署到华为云函数计算FunctionGraph&#xff0c;并一键开通周边依赖资源。 本次Serve…

搭建一个windows的DevOps环境记录

边搭建边记录&#xff0c;整个DevOps环境的搭建可能会很久。。。 一、安装Jenkins&#xff1a; 参考&#xff1a;Jenkins基础篇--windows安装Jenkins-CSDN博客 注意上面选择JDK的路径&#xff0c;选择到安装目录&#xff0c;该目录并不一定要在path中配置了&#xff08;就是…

Python中使用cv2.resize()函数批量自定义缩放图像尺寸

目录 常用插值缩放方法缩放示例代码总结 常用插值缩放方法 cv2.resize()函数中的interpolation参数指定了图像缩放时使用的插值方法。以下是常用的插值方法&#xff1a; cv2.INTER_NEAREST&#xff1a;最近邻插值。该方法通过选择最接近目标像素的原始像素来进行插值。它是最…

【Unity地编细节】为什么Unity笔刷在地形上面刷不出来

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 &#x1f636;‍&#x1f32b;️收录于专栏&#xff1a;unity细节和bug &#x1f636;‍&#x1f32b;️优质专栏 ⭐【…

python+unittest+requests+HTMLRunner编写接口自动化测试集

问题描述&#xff1a; 搭建接口测试框架&#xff0c;执行用例请求多个不同请求方式的接口 实现步骤&#xff1a; ① 创建配置文件config.ini&#xff0c;写入部分公用参数&#xff0c;如接口的基本url、测试报告文件路径、测试数据文件路径等配置项 1 [DATABASE] 2 data_addre…

redis的key超时策略和key淘汰机制(面试题详解)

ChatGPT给出的回答&#xff1a; Redis中的Key超时策略和Key淘汰机制是为了有效管理内存和控制数据的生命周期。 Key超时策略&#xff1a;Redis可以为每个Key设置过期时间&#xff0c;一旦Key过期&#xff0c;它将自动从Redis中删除。可以使用EXPIRE命令为Key设置过期时间&…

【自然语言处理】理解词向量、CBOW与Skip-Gram模型

文章目录 一、词向量基础知识1.1 One-hot表示1.2 Distributed表示 二、word2vec基础知识2.1 CBOW和Skip-gram 三、基于Hierarchical Softmax的 CBOW 模型和 Skip-gram 模型3.1 CBOW 模型3.2 Skip-gram 模型 参考资料 由于计算机不能直接对各种字符进行运算&#xff0c;为此需要…

党建展馆vr仿真解说员具有高质量的表现力和互动性

随着虚拟数字人应用渐成趋势&#xff0c;以虚拟数字人为核心的营销远比其他更能加速品牌年轻化进程和认识&#xff0c;助力企业在激烈的市场竞争中脱颖而出&#xff0c;那么企业虚拟IP代言人解决了哪些痛点? 解决品牌与代言人之间的风险问题 传统代言人在代言品牌时&#xff0…

【C语言|关键字】C语言32个关键字详解(4)——其他(typedef、sizeof)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

vue面试题及答案【集合目录】

前言&#xff1a; 欢迎浏览和关注本专栏《 前端就业宝典 》&#xff0c; 不管是扭螺丝还是造火箭&#xff0c; 多学点知识总没错。 这个专栏是扭螺丝之上要造火箭级别的知识&#xff0c;会给前端工作学习的小伙伴带来意想不到的帮助。 本专栏将前端知识拆整为零&#xff0c;主要…

【技能树笔记】网络篇——练习题解析(九)

目录 前言 一、OSPF双栈 1.1 OSPFv3 LSA 1.2 OSPFv3 二、ISIS双栈 2.1 ISISv6 2.2 ISIS高级特性 三、BGP双栈 四、PIM双栈 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filot…

2023 10月最新Vmd 下载安装教程,WindowsLinux

文章目录 下载Vmdwindows版本安装LINUX版本安装 下载Vmd 谷歌搜索VMD 点击左下角download VMD 可选择对应版本 注&#xff1a;点击后会出现输入用户名和密码&#xff0c;由于我已注册&#xff0c;界面不见了&#xff0c;所以直接描述一下。 输入用户名和密码然后会出现让登记…

AI工具大爆发,写作工具选择谁?

AI在生活中的发挥的作用越来越明显&#xff0c;许多人也想使用AI工具来提高自己的工作效率又或者学习效率&#xff0c;那么作为AI小白的我们该怎么选择写作工具呢&#xff1f;跟着小编的脚步&#xff0c;接着往下阅读。 首先我们需要选择一个适合自己的AI工具以便开展后续工作…

HTML图像标签

html文件&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>图像标签学习</title> </head> <body> <img src"../resources/image/01.jpg" alt"小狗图…

玩转 MaxCompute SQL 训练营! 数据分析挖掘迅速出师

云布道师 用 MaxCompute 在数据里面挖呀挖呀挖&#xff0c;写花样的 sql 分析花样的数据&#xff01;云原生大数据计算服务 MaxCompute 是企业级 Serverless 智能数仓&#xff0c;向用户提供了完善的数据导入方案以及多种经典的分布式计算模型&#xff0c;能够更快速的解决用户…

多变量GARCH模型R代码实现

大家好&#xff0c;我是带我去滑雪&#xff01; 多变量GARCH&#xff08;Generalized Autoregressive Conditional Heteroskedasticity&#xff09;模型是一种用于建模多个时间序列变量之间的条件异方差性&#xff08;conditional heteroskedasticity&#xff09;的统计模型。它…

一文读懂:什么是块存储、文件存储、对象存储?

大家好&#xff0c;我是小学僧。 提到"存储"&#xff0c; 你首先想到的是这个&#xff1f; 还是这个&#xff1f; 也或者还有这个&#xff1f; 哈哈&#xff0c;没错&#xff0c;我们生活中已经离不开存储&#xff0c;视频、音乐、图片、文本、表格这样的数据文件都…

mac上mongodb 以及可视化工具 下载以及安装

简介 1. 下载 官网上的下载地址藏得非常深&#xff0c;不花老半天 根本找不到 下载地址 https://www.mongodb.com/try/download/community 目前最新社区版本7.0.2 下载链接 mac intel芯片 &#xff1a; https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-7.0.2.tgz ma…

【Docker从入门到入土 5】 使用Docker-compose一键部署Wordpress平台

Docker-compose 一、YAML 文件格式及编写注意事项&#xff08;重要&#xff09;1.1 简介1.2 yaml语法特性1.3 yaml文件格式1.4 json格式简介 二、Docker-compose2.1 简介2.2 docker-compose的三大概念2.3 docker-compose配置模板文件常用的字段2.4 docker-compose 常用命令 三、…

1-08 移动端适配 rem+vm

移动端适配 remvm React配置postcss-px-to-viewport 安装依赖&#xff1a;在项目根目录下运行以下命令安装所需的依赖包&#xff1a; npm install postcss-px-to-viewport --save-dev配置代码 const path require(path);module.exports {webpack: {alias: {: path.resolv…