【数据结构】栈与队列的“双向奔赴”

目录

前言

1.使用“栈”检查符号是否成对出现

2.使用“栈”实现字符串反转

3.使用“队列”实现“栈”

4.使用“栈”实现“队列” 


前言

什么是栈?

  • 栈(stack)是一种特殊的线性数据集合,只允许在栈顶按照后进先出LIFO(Last In First Out)进行数据操作;

为什么使用栈?

  • 常见应用场景:浏览器的前进与回退操作、虚拟机栈等;

如何使用栈?

  • 栈的实现结构可以是一维数组或链表实现
  • 用数组实现的栈叫做顺序栈。在Java中,顺序栈使用java.util.Stack类实现
  • 用链表实现的栈叫做链式栈。在Java中,链式栈使用java.util.LinkedList类实现;
  • 入栈(push):将新元素放入栈顶,只允许从栈顶一侧放入元素,类似于弹匣装弹,只能从弹匣口依次压入弹匣内;

  • 出栈(pop):只有栈顶元素才允许出栈,类似于枪射出子弹时,子弹从弹匣口依次进入枪体射出;

  • 时间复杂度:
  1. 访问指定位置的元素:O(n)        ——>需要依次遍历所有元素,所需元素可能在栈底
  2. 入栈和出栈:O(1)                      ——>只涉及栈顶

什么是队列?

  • 队列(queue)是一种线性数据结构,队列中的元素按照先入先出的规则从队尾进入,队头出队;按照实现机制分为:单队列、循环队列;

为什么使用队列?

  • 常见应用场景:KTV点歌列表、阻塞队列、线程池的任务队列等;

如何使用队列?

  • 队列的实现结构可以是数组或链表实现
  • 用数组实现的队列叫做顺序队列。在Java中,顺序队列使用java.util.ArrayDeque类实现;
  • 用链表实现的队列叫做链式队列。在Java中,链式队列使用java.util.LinkedList类实现;
  • 入队(enqueue):只允许从队尾的位置放入元素,类似于银行取号等待叫号办理业务;

  • 出队(dequeue):只允许从队头的位置移出元素;

  • 假溢出:使用数组实现队列,执行出队操作时,指向队头和队尾的指针会向后移,队尾指针移动到最后的时候,无法添加数据,即使数组中之前出队的位置还要空闲空间,这种现象就是“假溢出”。

1. 使用“栈”检查符号是否成对出现

 public static boolean isValid(String s ){HashMap<Character, Character> mappings = new HashMap<>();mappings.put('}','{');mappings.put(')','(');mappings.put(']','[');Stack<Character> stack = new Stack<>();for(int i=0;i<s.length();i++){char c =s.charAt(i);if(mappings.containsKey(c)){//当前字符是“右括号”char topElement = stack.isEmpty() ? '#' :stack.pop();char left = mappings.get(c);if(left != topElement){return false;}}else {//当前字符是"左括号"stack.push(c);}}return stack.isEmpty();}

解读:

  • 创建一个HashMap mappings,用于存储右括号和对应的左括号的映射关系;
  • 创建一个Stack stack,用于存储遍历过程中遇到的左括号,以便后续进行匹配检查;
  • 进入for循环,遍历输入的字符串s。在循环中,取出字符串中的每个字符c;
  • 如果当前字符c存在于 mappings 中,即为右括号,那么就从栈中弹出栈顶元素,然后检查该右括号对应的左括号是否与弹出的左括号匹配,如果不匹配则返回false;
  • 如果当前字符c不存在于 mappings 中,即为左括号,将其压入栈中;
  • 循环结束后,检查栈是否为空,如果栈为空则说明所有的括号都匹配,返回true,否则返回false;
  • 测试用例
   public static void main(String[] args) {String str ="{[(!)]}";System.out.println(isValid(str));}
  • 测试结果


 2. 使用“栈”实现字符串反转

public static void main(String[] args) {String str ="just do it";StringBuilder stringBuilder = new StringBuilder(str);//使用栈实现字符串反转Stack<Character> stringStack = new Stack<>();//入栈for(int i=0;i<str.length();i++){stringStack.push(str.charAt(i));}//出栈while (!stringStack.empty()){str +=stringStack.pop();}System.out.println(stringBuilder);}

解读:

  • 创建一个Stack stringStack,用于存储字符串中的字符;
  • 进入for循环,遍历输入的字符串str,将字符串中的每个字符依次压入栈中;
  • 使用while循环,当栈不为空时,依次从栈中弹出字符,并将其拼接到原字符串str的末尾;
  • 循环结束后,str中存储的就是原字符串str的反转结果;
  • 测试结果


3. 使用“队列”实现“栈”

public class MyStack{private Queue<Integer> queue1; //出栈队列private Queue<Integer> queue2; //入栈队列public MyStack(){queue1 = new LinkedList<Integer>();queue2 = new LinkedList<Integer>();}public void push(int x){queue2.offer(x);while(!queue1.isEmpty()){queue2.offer(queue1.poll());}Queue<Integer> temp = queue1;queue1 = queue2;queue2 = temp;}public int pop(){return queue1.poll();}public int top(){return queue1.peek();}public boolean empty(){return queue1.isEmpty();}@Overridepublic String toString() {return queue1.toString();}
}

解读:

  • 定义了一个名为 MyStack 的类,其中包含两个私有属性 queue1 和 queue2,分别表示出栈队列和入栈队列,并在构造函数中对它们进行了初始化;
  • push 方法用于入栈操作,将元素加入 queue2 中,然后通过循环将 queue1 中的元素逐个转移到 queue2 中,以确保新入栈的元素位于队列的头部(因为队列的特性是先进先出)。最后交换 queue1 和 queue2 的引用,使得 queue1 始终指向当前栈中的元素所在的队列;
  • pop 方法用于出栈操作,直接从 queue1 中弹出元素即可;
  • top 方法用于获取栈顶元素,直接返回 queue1 的头部元素;
  • empty 方法用于判断栈是否为空,直接返回 queue1 是否为空的结果;

用两个队列模拟栈的基本操作,通过不断在两个队列之间转移元素,使得栈的操作可以在队列上进行;

  •  测试用例
 public static void main(String[] args) {MyStack myStack = new MyStack();//入栈myStack.push(1);myStack.push(2);myStack.push(3);myStack.push(4);myStack.push(5);System.out.println("入栈后"+myStack);System.out.println("入栈后栈顶元素:"+myStack.top());//出栈myStack.pop();myStack.pop();myStack.pop();myStack.pop();myStack.pop();System.out.println("出栈后"+myStack);System.out.println("出栈后栈是否为空:"+myStack.empty());}
  • 测试结果


4. 使用“栈”实现“队列” 

public class Queue{//入队栈private Stack<Integer> inStack = new Stack<>();//出队栈private Stack<Integer> outStack = new Stack<>();//入队public void offer(int item){while(!outStack.empty()){inStack.push(outStack.pop());}//新元素入队inStack.push(item);}//出队public int poll(){while(!inStack.empty()){outStack.push(inStack.pop());}return outStack.pop();}//判断是否为空public boolean empty(){return outStack.size() == 0 && inStack.size() == 0;}@Overridepublic String toString() {return inStack.toString();}
}

解读:

  • offer 方法用于向队列中添加元素。首先,它会将 outStack 中的元素逐个弹出并压入 inStack 中,这样可以确保之前入队的元素在 inStack 的底部,新的元素可以被放在队列的末尾,接着,将新元素直接入栈到 inStack 中,表示将新元素放入队列中。
  • poll 方法用于从队列中取出元素。首先,它会将 inStack 中的元素逐个弹出并压入 outStack 中,这样可以确保队列的头部元素位于 outStack 的栈顶,然后,从 outStack 中弹出栈顶元素,并作为出队操作的结果返回。
  • empty 方法用于检查队列是否为空。只有当 inStack 和 outStack 都为空时,才表示整个队列为空;

基于两个栈实现队列的方法称为双栈法,通过巧妙地利用栈的特性,可以实现队列的先进先出(FIFO)功能。在实际应用中,双栈法可以用于需要频繁进行队列操作的场景,同时也可以作为栈和队列之间的一个有趣的数据结构转换方式。

  • 测试用例
 public static void main(String[] args) {Queue myQueue = new Queue();//入队myQueue.offer(1);myQueue.offer(2);myQueue.offer(3);myQueue.offer(4);myQueue.offer(5);System.out.println("入队后:"+myQueue);//出队myQueue.poll();myQueue.poll();myQueue.poll();myQueue.poll();myQueue.poll();System.out.println("出队后是否为空:"+myQueue.empty());}
  • 测试结果

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

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

相关文章

网上商城购物系统|基于springboot框架+ Mysql+Java+B/S架构的网上商城购物系统设计与实现(可运行源码+数据库+设计文档+部署说明)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 管理员功能登录前台功能效果图 用户功能模块 系统功能设计 数据库E-R图设计 lunwen参…

ip广播智慧工地广播喊话号角 IP网络号角在塔吊中应用 通过寻呼话筒预案广播

ip广播智慧工地广播喊话号角 IP网络号角在塔吊中应用 通过寻呼话筒预案广播 SV-704XT是深圳锐科达电子有限公司的一款壁挂式网络有源号角&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和号角喇叭输出播放&#xff0c;可达到功率50W。SV-704XT内置有…

OneDrive教育版迁移记录

背景 微软再次削减教育版优惠的OneDrive容量&#xff0c;从原先的5T直接砍到100G/人&#xff0c;同时对每个学校保留总共100TB的共享存储容量。 右键Onedrive图标——设置——存储容量可见 100GB对于重度用户显然是不够使用的&#xff0c;为此笔者改换Microsoft Office365家庭…

mac启动skywalking报错

这个命令显示已经成功 但是日志报错了以上内容。 然后去修改。vim .bash_profile 查看全局变量&#xff0c;这个jdk却是有2个。所以这个问题没解决。

【哈希映射】【 哈希集合】 381. O(1) 时间插入、删除和获取随机元素 - 允许重复

作者推荐 视频算法专题 本文涉及知识点 哈希映射 哈希集合 LeetCode 381. O(1) 时间插入、删除和获取随机元素 - 允许重复 RandomizedCollection 是一种包含数字集合(可能是重复的)的数据结构。它应该支持插入和删除特定元素&#xff0c;以及删除随机元素。 实现 Randomiz…

python爬虫实战——小红书

目录 1、博主页面分析 2、在控制台预先获取所有作品页的URL 3、在 Python 中读入该文件并做准备工作 4、处理图文类型作品 5、处理视频类型作品 6、异常访问而被中断的现象 7、完整参考代码 任务&#xff1a;在 win 环境下&#xff0c;利用 Python、webdriver、JavaS…

<.Net>VisaulStudio2022下用VB.net实现socket与汇川PLC进行通讯案例(Eazy521)

前言 此前&#xff0c;我写过一个VB.net环境下与西门子PLC通讯案例的博文&#xff1a; VisaulStudio2022下用VB.net实现socket与西门子PLC进行通讯案例&#xff08;优化版&#xff09; 最近项目上会用到汇川PLC比较多&#xff0c;正好有个项目有上位机通讯需求&#xff0c;于是…

[剪藏] - 由哇哈哈和农夫山泉所想到的

哇哈哈和农夫山泉的缠斗最近冒出来一个有趣的点&#xff1a;营销大于内容的胜利。 具体来说是这样的&#xff1a;农夫山泉很多年前做广告&#xff0c;说纯净水没有矿物质&#xff0c;长期喝是不利于人体健康的。农夫还做了个营销的对比实验&#xff0c;大概是用矿泉水养水仙花&…

音视频开发之旅(75)- AI数字人进阶--GeneFace++

目录 1.效果展示和玩法场景 2.GeneFace原理学习 3.数据集准备以及训练的过程 5.遇到的问题与解决方案 6.参考资料 一、效果展示 AI数字人进阶--GeneFace&#xff08;1&#xff09; AI数字人进阶--GeneFace&#xff08;2&#xff09; 想象一下&#xff0c;一个专为你打造的…

为什么 VSCode 不用 Qt 而要用 Electron?

为什么 VSCode 不用 Qt 而要用 Electron? 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Qt 的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&am…

Python基础课堂最后一课23——正则对象

文章目录 前言一、正则对象是什么&#xff1f;二、正则表达式基本分类1.普通字符2.元字符 总结 前言 很开心能和你们一些学习进步&#xff0c;在这一个多月的时间中&#xff0c;是你们让我坚持了下来&#xff0c;完成了python基础课堂编写&#xff0c;不管如何&#xff0c;我们…

Linux系统——Nginx脚本拦截拓展

可能会有些无聊的人对服务器的Nginx服务进行恶意访问网站、API接口&#xff0c;会影响到用户的体验&#xff0c;我们可以做一个简单的脚本对恶意访问的IP做一个有效的拦截&#xff0c;揪出这些IP地址&#xff0c;然后将其进行禁用。 在Nginx的conf目录下新建一个blockip.conf文…

certificate has expired or is not yet valid:npm和node证书过期问题

在 1 月 22 日&#xff0c;淘宝原镜像域名&#xff08;registry.npm.taobao.org&#xff09;的 HTTPS 证书正式到期。如果想要继续使用&#xff0c;需要将 npm 源切换到新的源&#xff08;registry.npmmirror.com&#xff09;&#xff0c;否则会报错。 解决方案切换到新的源&a…

HTML表单

本文章属于学习笔记&#xff0c;在https://www.freecodecamp.org/chinese/learn/2022/responsive-web-design/中练习 四、HTML表单 CSS 1、vh单位表示视口高度&#xff0c;等于视口高度的1%。这使得它相对于视口高度。height:100vh; 2、设置 body 的默认 margin 为 0 来重置…

【掌握版本控制:Git 入门与实践指南】远程操作|标签管理

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;泥中に咲く—ウォルピスカーター 0:34━━━━━━️&#x1f49f;──────── 4:46 &#x1f504; ◀️ ⏸ ▶…

汽车IVI中控开发入门及进阶(十三):语音识别

前言: IVI中控上的语音识别,在目前市场上也是非常显眼的一个创新,大幅改变了传统IVI的操作习惯。 语音识别Speech recognition,也称为自动语音识别(ASR)、计算机语音识别或语音到文本,是一种使程序能够将人类语音处理成书面格式的能力。 语音识别Speech recognition是计…

数码管的静态显示(二)

1.原理 要按照上图的顺序传递位选和段选的数据。 因为q0是最高位&#xff0c;共阳极数码管结构是dp....a&#xff0c;所以应该先传入低位a&#xff0c;而a在上图中的8段2进制编码中是seg[7]&#xff0c;所以段选信号的顺序是seg[0],...seg[7]。 因为输出信号是两个时钟&#x…

Docker入门笔记(1)

Docker入门笔记&#xff08;1&#xff09; 容器技术入门 之前我的WIT问卷管理系统在阿里云上部署需要好多配置&#xff0c;各个环境耦合的比较紧密&#xff0c;花了不少时间去做部署和调配。 现在有了Docker以后&#xff0c;我们可以把各种组件配置好&#xff0c;然后打包成…

使用ScottPlot库在.NET WinForms中快速实现大型数据集的交互式显示

前言 在.NET应用开发中数据集的交互式显示是一个非常常见的功能&#xff0c;如需要创建折线图、柱状图、饼图、散点图等不同类型的图表将数据呈现出来&#xff0c;帮助人们更好地理解数据、发现规律&#xff0c;并支持决策和沟通。本文我们将一起来学习一下如何使用ScottPlot库…

websocket逆向案例

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、案例地址二、分析流程三、逆向参数四、webSocket 交互位置总结 前言 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供…