C++STL~~stackqueue

文章目录

    • 容器适配器
    • 一、stack&queue的概念
    • 二、stack&queue的使用
    • 三、stack&queue的练习
    • 四、总结

容器适配器

什么是适配器
适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。
在这里插入图片描述
STL标准库中stack和queue的底层结构
虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stack和队列只是对其他容器的接口进行了包装,STL中stack和queue默认使用deque(双端队列容器)
在这里插入图片描述
在这里插入图片描述

一、stack&queue的概念

stack(栈)
概念和特点
栈是一种后进先出(Last In First Out,LIFO)的数据结构。就像一叠盘子,最后放上去的盘子最先被拿走。
在这里插入图片描述

queue(队列)
概念和特点
队列是一种先进先出(First In First Out,FIFO)的数据结构。类似于排队买东西,先到的人先得到服务。
在这里插入图片描述

二、stack&queue的使用

stack的使用
在这里插入图片描述

例如:

#include <iostream>
#include <stack>int main() {std::stack<int> s;// 向栈中压入一些元素s.push(10);s.push(20);s.push(30);// 输出栈的大小std::cout << "初始栈的大小为:" << s.size() << std::endl;// 检查栈是否为空if (!s.empty()) {std::cout << "栈不为空。" << std::endl;}// 获取栈顶元素并输出std::cout << "栈顶元素为:" << s.top() << std::endl;// 弹出栈顶元素s.pop();// 再次输出栈顶元素和栈的大小std::cout << "弹出一个元素后,栈顶元素为:" << s.top() << std::endl;std::cout << "此时栈的大小为:" << s.size() << std::endl;// 继续弹出元素直到栈为空while (!s.empty()) {s.pop();}// 检查栈是否为空if (s.empty()) {std::cout << "栈已为空。" << std::endl;}return 0;
}
}

首先向栈中压入一些元素,然后展示了如何使用size获取栈的大小,empty判断栈是否为空,top获取栈顶元素,以及pop弹出栈顶元素。
queue的使用
在这里插入图片描述

#include <iostream>
#include <queue>int main() {std::queue<int> q;// 检查初始时队列是否为空std::cout << "初始时队列是否为空:" << (q.empty()? "是" : "否") << std::endl;std::cout << "初始队列大小:" << q.size() << std::endl;// 向队列中添加元素q.push(10);q.push(20);q.push(30);// 输出队列的大小和队首、队尾元素std::cout << "添加元素后队列大小:" << q.size() << std::endl;std::cout << "队首元素(front):" << q.front() << std::endl;std::cout << "队尾元素(back):" << q.back() << std::endl;// 弹出一个元素q.pop();// 再次输出队列的大小和队首、队尾元素std::cout << "弹出一个元素后队列大小:" << q.size() << std::endl;std::cout << "队首元素(front):" << q.front() << std::endl;std::cout << "队尾元素(back):" << q.back() << std::endl;// 检查队列是否为空std::cout << "此时队列是否为空:" << (q.empty()? "是" : "否") << std::endl;return 0;
}

首先展示了初始时队列的空状态和大小,然后添加元素后展示了队列的大小、队首和队尾元素,接着弹出一个元素后再次展示相关信息,最后检查队列是否为空。需要注意的是,queue中没有top函数,因为queue的特点决定了只能从队首和队尾进行操作。

三、stack&queue的练习

1.最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类: MinStack() 初始化堆栈对象。 void push(int val) 将元素val推入堆栈。 void
pop() 删除堆栈顶部的元素。 int top() 获取堆栈顶部的元素。 int getMin() 获取堆栈中的最小元素。


输入: [“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]

输出: [null,null,null,null,-3,null,0,-2]

思路:

  • 1.首先,使用一个普通的栈来存储元素,这个栈用于实现push、pop和top操作。
  • 2.为了能够在常数时间内获取最小元素,再使用另一个栈来存储当前的最小元素。每当向主栈中压入一个元素时,如果这个元素小于等于辅助栈的栈顶元素(或者辅助栈为空时),就将这个元素也压入辅助栈。这样,辅助栈的栈顶始终是当前主栈中的最小元素。
  • 3.当执行pop操作时,如果弹出的元素等于辅助栈的栈顶元素,那么也从辅助栈中弹出这个元素,以保证辅助栈的栈顶始终是当前主栈中的最小元素。
#include <iostream>
#include <stack>class MinStack {
private:std::stack<int> mainStack;std::stack<int> minStack;
public:MinStack() {}void push(int val) {mainStack.push(val);if (minStack.empty() || val <= minStack.top()) {minStack.push(val);}}void pop() {if (mainStack.top() == minStack.top()) {minStack.pop();}mainStack.pop();}int top() {return mainStack.top();}int getMin() {return minStack.top();}
};

使用以下方式测试这个类

int main() {MinStack minStack;minStack.push(-2);minStack.push(0);minStack.push(-3);std::cout << minStack.getMin() << std::endl;minStack.pop();std::cout << minStack.top() << std::endl;std::cout << minStack.getMin() << std::endl;return 0;
}

2.栈的弹出压入序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

  1. 0<=pushV.length == popV.length <=1000
  2. -1000<=pushV[i]<=1000
  3. pushV 的所有数字均不相同

示例1 输入: [1,2,3,4,5],[4,5,3,2,1] 返回值:true 说明:
可以通过push(1)=>push(2)=>push(3)=>push(4)=>pop()=>push(5)=>pop()=>pop()=>pop()=>pop() 这样的顺序得到[4,5,3,2,1]这个序列,返回true
示例2
输入:[1,2,3,4,5],[4,3,5,1,2]
返回值:false
说明:
由于是[1,2,3,4,5]的压入顺序,[4,3,5,1,2]的弹出顺序,要求4,3,5必须在1,2前压入,且1,2不能弹出,但是这样压入的顺序,1又不能在2之前弹出,所以无法形成的,返回false

思路:

  • 1.使用一个辅助栈来模拟入栈和出栈的过程。
  • 2.遍历压入序列pushV,将元素依次压入辅助栈。
  • 3.同时,遍历弹出序列popV,检查辅助栈的栈顶元素是否与当前要弹出的元素相等。如果相等,则从辅助栈弹出该元素,继续检查下一个弹出元素;如果不相等,则继续从压入序列中压入元素到辅助栈,直到辅助栈的栈顶元素与当前要弹出的元素相等或者压入序列遍历完。
  • 4.如果最终辅助栈为空,说明弹出序列是可能的,否则不可能。
#include <iostream>
#include <vector>
#include <stack>class Solution {
public:bool isPopOrder(std::vector<int> pushV, std::vector<int> popV) {std::stack<int> s;int i = 0, j = 0;while (i < pushV.size()) {s.push(pushV[i++]);while (!s.empty() && s.top() == popV[j]) {s.pop();j++;}}return s.empty();}
};

使用以下方式测试这个函数

int main() {Solution solution;std::vector<int> pushV = {1, 2, 3, 4, 5};std::vector<int> popV = {4, 5, 3, 2, 1};bool result = solution.isPopOrder(pushV, popV);std::cout << (result? "true" : "false") << std::endl;return 0;
}

3.二叉树的分层遍历**
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
在这里插入图片描述
思路

  • 1.使用一个队列来实现层序遍历。首先将根节点入队。
  • 2.不断循环,当队列不为空时:
    • 记录当前队列的大小size,这个大小表示当前层的节点个数。
    • 遍历当前层的所有节点,对于每个节点:
    • 取出节点的值,将其加入到结果列表中。
    • 如果该节点有左子节点,将左子节点入队。
    • 如果该节点有右子节点,将右子节点入队。
  • 3.循环结束后,就得到了二叉树的层序遍历结果。
#include <iostream>
#include <vector>
#include <queue>// 定义二叉树节点结构体
struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};class Solution {
public:std::vector<std::vector<int>> levelOrder(TreeNode* root) {std::vector<std::vector<int>> result;if (!root) return result;std::queue<TreeNode*> q;q.push(root);while (!q.empty()) {int size = q.size();std::vector<int> level;for (int i = 0; i < size; i++) {TreeNode* node = q.front();q.pop();level.push_back(node->val);if (node->left) q.push(node->left);if (node->right) q.push(node->right);}result.push_back(level);}return result;}
};

使用以下方式测试这个函数

int main() {// 构建二叉树TreeNode* root = new TreeNode(3);root->left = new TreeNode(9);root->right = new TreeNode(20);root->right->left = new TreeNode(15);root->right->right = new TreeNode(7);Solution solution;std::vector<std::vector<int>> result = solution.levelOrder(root);for (const auto& level : result) {for (int val : level) {std::cout << val << " ";}std::cout << std::endl;}// 释放内存delete root->right->right;delete root->right->left;delete root->right;delete root->left;delete root;return 0;
}

四、总结

关于数据结构版本的stack&queue:数据结构~~栈和队列
栈(Stack)

  1. 后进先出原则。

  2. 主要操作包括入栈(push)和出栈(pop)。

  3. 常用于函数调用、表达式求值、括号匹配等场景。

队列(Queue)

  1. 先进先出原则。

  2. 主要操作包括入队(enqueue)和出队(dequeue)。

  3. 常用于任务调度、排队系统、广度优先搜索等。

两者都是基本的数据结构,具有不同的特点和适用场景,在程序设计中发挥着重要作用。

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

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

相关文章

Leetcode 移动零

要求将数组中的所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。下面是该题的 C 解决方案&#xff1a; class Solution { public:void moveZeroes(vector<int>& nums) {int nonZeroPos 0; // 记录非零元素应该放置的位置// 遍历数组&#xff0c;…

【北京迅为】《STM32MP157开发板使用手册》- 第三十章Cortex-M4通用定时器实验

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

相图的科学应用,陶瓷材料创新

陶瓷材料因其优异的物理和化学性能&#xff0c;在航空航天、电子、生物医学等多个领域展现出广阔的应用前景。陶瓷材料的性能很大程度上取决于其微观结构&#xff0c;包括晶粒大小、相组成和分布。相图作为描述陶瓷材料在不同条件下的相变行为和相平衡关系的图表反映了陶瓷材料…

Element-ui el-table 全局表格排序

实现效果如下&#xff1a; 一、当页数据排序 如果只想要当前页面排序&#xff0c;只会涉及到前端&#xff0c;只需在<el-table-column>标签上添加 :sortable"true"即可 二、自定义排序 如果想要全局排序&#xff0c;需要自定义排序函数&#xff0c;请求后台排…

Springboot项目打war包运行及错误解决

一,打war包 1. 修改pom.xml 为了不影响原pom.xml, 我复制了一个文件叫pom_war.xml , 需要打war包就采用pom_war.xml进行打war包, 你也可以直接修改pom.xml ① 打包方式改为war 没有就增加此配置 <packaging>war</packaging> ② 排除内嵌tomcat依赖 <de…

怎样在备忘录中添加提醒?怎么设置备忘录提醒

备忘录作为我们日常生活中常用的软件&#xff0c;其记录事项的便捷性已经得到了广泛认可。无论是工作计划、购物清单还是个人日记&#xff0c;备忘录都能帮助我们将这些信息快速记录下来。然而&#xff0c;如果备忘录能够进一步提供提醒功能&#xff0c;那么它将变得更加实用&a…

122.rk3399 uboot(2017.09) 源码分析2-initf_dm(2024-09-09)

这里接着上一篇来吧&#xff1a; https://blog.csdn.net/zhaozhi0810/article/details/141927053 本文主要是dm_init_and_scan函数的分析&#xff0c;这个内容比较复杂&#xff0c;我也是第一次阅读&#xff0c;错误之处在所难免&#xff0c;请多指教。 uboot的dm框架需要了解…

MyBatis 面试题11-27

11、Mybatis 是如何将 sql 执行结果封装为目标对象并返回的? 都有哪些映射形式&#xff1f; Mybatis 在执行 SQL 查询后&#xff0c;会将结果集封装为目标对象并返回。这主要依赖于 Mybatis 的映射机制&#xff0c;它提供了两种主要的映射形式&#xff1a; 第一种&#xff1…

代码质量护航:结合Checkstyle、SpringBoot与Git的最佳实践

在团队开发中&#xff0c;保持一致的代码风格和高质量的代码至关重要。为了提升团队的整体代码质量&#xff0c;防止低质量代码的提交&#xff0c;使用工具对代码进行自动化检查是非常有效的手段之一。在这篇博客中&#xff0c;我将介绍如何通过结合 Checkstyle、Spring Boot 和…

Zotero使用(一)PDF文件导入不会自动识别

上面两种&#xff0c;一种中文&#xff0c;一种英文&#xff0c;会发现&#xff0c;中文的导入进去之后不会自动识别&#xff0c;部分英文也是。不能自动识别就会缺少导出参考文献的功能&#xff0c;怎么办&#xff1f; 发现之前导入喜欢使用PDF格式 可以结合.ris格式&#xf…

网络安全 day5 --- 反弹SHELL不回显带外正反向连接防火墙出入站文件下载

免责声明 本免责声明适用于作者所有文章内容。使用者需明确&#xff0c;网络安全技术仅供学习和合法研究使用&#xff0c;不得用于任何非法活动&#xff0c;如未经授权的入侵、攻击或数据窃取&#xff0c;所有相关法律责任由使用者自行承担。由于网络安全操作可能带来系统崩溃、…

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统 在产品将要上线之前&#xff0c;需要制作不同类型格式的根文件系统 在产品研发阶段&#xff0c;我们还是需要使用nfs的方式挂载根文件系统 优点&#xff1a;可以直接在上位机中修改文件系统内容&#xff0c;延长EMMC的寿命 【1】重启上位机nfs服…

【计算机网络】HTTPHTTPS

HTTP&HTTPS HTTP协议初识HTTP如何抓包Fiddler的使用抓包查看包的信息 报文格式请求报文响应报文报文对比 URLHTTP方法认识Header初识状态码 HTTPS协议为什么需要 HTTPS加密基础知识HTTPS的工作流程引入对称加密引入非对称加密引入证书HTTPS 的工作流程 浏览器从输入URL到展…

短视频剪辑从简单到复杂,这四款很OK!

作为一个刚刚踏入视频剪辑世界的新手&#xff0c;我最近可是忙得不亦乐乎。我尝试了四款流行的视频剪辑软件&#xff0c;今天&#xff0c;就让我来和大家分享一下我的使用感受&#xff0c;看看哪款软件更适合我们这些初学者。这里先说一句&#xff0c;选择视频剪辑软件就像挑衣…

opencv学习:calcHist 函数绘制图像直方图及代码实现

cv2.calcHist 函数是 OpenCV 库中用于计算图像直方图的函数。直方图是一种统计图像中像素值分布的工具&#xff0c;它可以提供图像的亮度、颜色等信息。这个函数可以用于灰度图像和彩色图像。 函数语法 hist cv2.calcHist(images, channels, mask, histSize, ranges, accumu…

解决 PyCharm 无法启动 Jupyter 服务器的问题:报错分析与解决方案

文章目录 报错背景报错详细信息解决方案pycharm 设置 报错背景 在使用 pycharm 付费版的过程中&#xff0c;发现一直无法启动 jupyter 服务器。 一直也不知道是为什么&#xff0c;直到在终端输入&#xff1a; jupyter notebook发现 jupyter 服务无法启动。 报错详细信息 下…

数据库系列之GaussDB数据库中逻辑对象关系简析

初次接触openGauss或GaussDB数据库的逻辑对象&#xff0c;被其中的表空间、数据库、schema和用户之间的关系&#xff0c;以及授权管理困惑住了&#xff0c;与熟悉的MySQL数据库的逻辑对象又有明显的不同。本文旨在简要梳理下GaussDB数据库逻辑对象之间的关系&#xff0c;以加深…

浅谈EXT2文件系统(1)

简介 EXT2&#xff08;Second Extended Filesystem&#xff09;文件系统是Linux操作系统的早期文件系统之一&#xff0c;它于 1993 年推出&#xff0c;是第一个旨在克服 Ext 文件系统限制的商业文件系统。EXT2 没有日志功能&#xff0c;EXT2 支持的单个文件大小为 2TB&#xf…

如何在Word中插入复选框

如何在Word中插入复选框&#xff1a;详细教程与技巧 在Word中插入复选框是一项非常实用的技巧&#xff0c;尤其是在制作问卷调查、待办事项清单、交互式表单或文档中需要用户进行选择时&#xff0c;复选框不仅能提高文档的功能性&#xff0c;还能显得更加专业。本文将详细讲解…

不小心把回收站清空了怎么恢复?别慌!四招找回

在日常使用电脑的过程中&#xff0c;我们可能会不小心清空回收站&#xff0c;从而丢失一些重要的文件。当遇到这种情况时&#xff0c;很多人可能会感到焦虑和无助。然而&#xff0c;幸运的是&#xff0c;有一些方法可以帮助我们尝试恢复这些被删除的文件。下面&#xff0c;我们…