顺序栈的实现----数据结构
栈的概念
对于栈(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;
}
代码很多,但是结构清楚。以下是代码的执行效果,能清楚知道移动的轨迹。
相关文章:

顺序栈的实现----数据结构
栈的概念 对于栈(Stack),后进先出(Last In First Out,LIFO),栈也是一种线性表,只不过是一种操作受限的线性表,只能在一端操作,也就是不允许在中间进行查找、…...
k8s calico 网络原理
一、cluster ip Cluster IP 是 Kubernetes 中 Service 的 IP 地址,它是一个虚拟 IP 地址,用于集群内的 Pod 相互通信。 例如: Cluster IP:2.2.2.2负载的真实Pod IP:1.1.1.1 场景: Pod A 的 IP 地址是 …...
【Python学习笔记】循环
Python中有两种类型的循环: while 循环 和 for 循环 1. while 循环 while循环是: 检查一个条件表达式,只要条件表达式计算结果为True 时, 就执行下面缩进的代码。 如此反复,直到条件表达式计算结果为False时,结束 循…...

1 如何入门TensorFlow
近年来人工智能的火爆吸引了很多人,网上相关的热门课程报名的人很多,但是坚持下去的人却少。那些晦涩的原理没有一定知识的积累很难能理解。 如果你对人工智能感兴趣,且想利用人工智能去实现某项功能,而不是对人工智能本身感兴趣&…...

QTday02(常用类、UI界面下的开发、信号与槽)
今日任务 1. 使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin"&#x…...

自然语言处理---RNN经典案例之使用seq2seq实现英译法
1 seq2seq介绍 1.1 seq2seq模型架构 seq2seq模型架构分析: seq2seq模型架构,包括两部分分别是encoder(编码器)和decoder(解码器),编码器和解码器的内部实现都使用了GRU模型,这里它要完成的是一个中文到英文的翻译:欢迎…...
Python【判断列表的存在与否关系】
要求:使用列表判断一个列表是否在另外一个列表中 代码如下: list1 [1, 2, 6, 8, 7, 10, 5] print("列表1为:", list1) list2 [2, 6, 5, 10] print("列表2为:",list2) res False a 0 for i in list2:if …...
MyBatis篇---第三篇
系列文章目录 文章目录 系列文章目录一、如何执行批量插入?二、Xml映射文件中,除了常见的select|insert|updae|delete标签之外,还有哪些标签?三、MyBatis实现一对一有几种方式?具体怎么操作的?一、如何执行批量插入? 首先,创建一个简单的insert语句: <insert id=”…...

uview1.0部分机型u-input组件禁用后无法触发click事件
最近,线上的一个 App 收到用户反馈,输入框禁用状态下点击无法拉起模态框。找了一下身边可用机型进行了测试,起初所有机型都没有复现这个问题,突然有一天 Redmi K30S Ultra 出现了异常,点击输入框无法触发点击事件&…...
Arduino IDE + Esp32 Cam + 实现视频流 + 开发环境部署
1、开发环境 Arduino ide 版本:2.2.1 esp32工具:2.0.5 示例代码 #include "esp_camera.h" #include <WiFi.h>// // WARNING!!! PSRAM IC required for UXGA resolution and high JPEG quality // Ensure ESP32 Wrover Modu…...

Day4力扣打卡
打卡记录 同积元组(哈希表 排列组合) 链接 思路:用哈希表将数组中出现的两不同数乘积依次记录,将出现两次以上的乘积组通过排列组合计算总情况个数。 class Solution { public:int tupleSameProduct(vector<int>& num…...

Paper Reading:《Consistent-Teacher: 减少半监督目标检测中不一致的伪目标》
目录 简介工作重点方法ASA, adaptive anchor assignmentFAM-3D, 3D feature alignment moduleGMM, Gaussian Mixture Model实施细节 实验与SOTA的比较消融实验 总结 简介 题目:《Consistent-Teacher: Towards Reducing Inconsistent Pseudo-targets in Semi-supervi…...

设计模式:观察者模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)
简介: 观察者模式,它是一种行为型设计模式,它允许一个对象自动通知其依赖者(观察者)状态的变化。当被观察者的状态发生改变时,它会通知所有的观察者对象,使他们能够及时做出响应。在观察者模式…...
kotling构造函数
Kotlin-继承与构造函数 - 简书 (jianshu.com) Kotlin语言中的继承与构造函数(详解)_kotlin 继承 构造函数_young螺母的博客-CSDN博客...

SpringMVC - 详解RESTful
文章目录 1. 简介2. RESTful的实现3.HiddenHttpMethodFilter4. RESTful案例1、准备工作2、功能清单3、具体功能:访问首页a>配置view-controllerb>创建页面 4、具体功能:查询所有员工数据a>控制器方法b>创建employee_list.html 5、具体功能&a…...

html表格标签
<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body><!--表格table 行 tr 列 td --> <table border"1px"><tr> <!--colsp…...

Node.JS---npm相关
文章目录 前言一、package.json配置项version:1.0.0devDependenciesdependenciespeerDependenciesoptionalDependencies 二、npm命令1、npm config listxmzs使用2、npm installpackage-lock.json作用 3、npm run4、 查看全局安装的可执行文件 npm生命周期npxnpx简介…...

Flutter的Don‘t use ‘BuildContext‘s across async gaps警告解决方法
文章目录 问题有问题的源码 问题原因问题分析Context的含义BuildContext的作用特殊情况 解决方法 问题 Flutter开发中遇到Don’t use BuildContext’s across async gaps警告 有问题的源码 if (await databaseHelper.isDataExist(task.title)) {showDialog(context: context,…...

Nginx 实战教程
本篇博客我会演示日常的工作中,我们是怎么利用nginx部署项目的。我们以部署一套前后分离的项目为本次讲述的内容 一、搭建后端项目 创建一个最简单的springboot项目: 只需要依赖一个web模块即可: 提供一个api接口,可以获取服务端…...
Web自动化——python
文章目录 1.八大元素定位2.元素基本操作3.浏览器常用操作4.获取元素信息的常用方法5.鼠标和键盘相关操作6.元素等待1.隐式等待2.显示等待 7.下拉选择框8.弹出框9.滚动条操作10.frame表单的切换11.多窗口切换12.窗口截图、验证码处理 1.八大元素定位 元素属性定位:id…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...