C++栈、队列

文章目录

目录

文章目录

前言

一、stack、queue介绍

       1.stack

        2.queue

二、stack、queue的习题

        1. 最小栈

2. 栈的压入、弹出序列

3.二叉树的层序遍历

三、stack和queue的模拟实现

        1.stack的模拟实现

2.queue的模拟实现


前言

        栈和队列是俩种特殊的容器,C++在实现栈和队列时,复用了vector和list容器。本章内容我们将介绍和模拟实现stack(栈)和queue(队列)。以及做几道关于stack和queue的题。加深对stack和queue的理解。


一、stack、queue介绍

       1.stack

        stack的文档介绍icon-default.png?t=N7T8https://legacy.cplusplus.com/reference/stack/stack/?kw=stack

翻译:
        1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。
        2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。
        3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:

        empty:判空操作
        back:获取尾部元素操作
        push_back:尾部插入元素操作
        pop_back:尾部删除元素操作

        4. 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque。

stack的接口:

函数说明接口说明
stack()构造空的栈
empty()检测stack是否为空
size()返回stack中元素的个数
top()返回栈顶元素的引用
push()将元素val压入stack中
pop()将stack中尾部的元素弹出

        2.queue

        queue - C++ Reference (cplusplus.com)icon-default.png?t=N7T8https://legacy.cplusplus.com/reference/queue/queue/翻译:
        1. 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。
        2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。
        3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:

empty:检测队列是否为空
size:返回队列中有效元素的个数
front:返回队头元素的引用
back:返回队尾元素的引用
push_back:在队列尾部入队列
pop_front:在队列头部出队列

        4. 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。

queue的接口:

函数声明接口说明
queue()构造空的队列
empty()检测队列是否为空,是返回true,否则返回false
size()返回队列中有效元素的个数
front()返回队头元素的引用
back()返回队尾元素的引用
push()在队尾将元素val入队列
pop()将队头元素出队列

二、stack、queue的习题

        1. 最小栈

155. 最小栈 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/min-stack/

       思路:使用俩个栈,一个栈用于存储所有数据,另一个栈用于记录动态记录最小数据(栈顶为最小数据).

        

        1.如果st为空,第一次Push时,minst也应该push

        2.在之后的每一次push,都要与minst的栈顶元素进行比较,如果<=minst栈顶元素,minst就也需要push该数据。否则只需要push到st。如图,push了1、2、0.最小的就是minst栈顶元素。

        (等于的时候minst也要push的原因,是因为pop时,如果有俩个相同的最小元素,最终最小元素不会记录):

        如图再次push0,但未记录,pop 0 时minst栈顶结果不对。

        3.在每次pop的时候和minst栈顶元素进行比较,如果等于栈顶元素则minst也需要pop掉。(因为在2步骤我们保证了minst的栈顶是最小值)

代码:

class MinStack {
public:MinStack() {//构造可以不写,因为stack是自定义类型会自动调用它的构造。}void push(int val) {//minst为空minst push。不为空进行比较st.push(val);if(minst.empty() || st.top() <= minst.top()){minst.push(val);}}void pop() {//和minst栈顶元素相同minst popif(st.top() == minst.top()){minst.pop();}st.pop();}int top() {return st.top();}int getMin() {return minst.top();}stack<int> st;stack<int> minst;
};

2. 栈的压入、弹出序列


栈的压入、弹出序列_牛客题霸_牛客网 (nowcoder.com)icon-default.png?t=N7T8https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId=13&&tqId=11174&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking

        已知入栈和出栈序列:vector<int>

首先我们需要有一个栈,按照入栈序列的顺序进行入栈。

思路:

        1.先入一个栈。

        2.s的栈顶元素和popV的栈顶元素(顺序就是出栈顺序)比较:
                a.如果相同,出栈序列往后走,栈顶元素pop掉。(说明以及匹配了出栈的顺序)

相同了,pop掉4,popi往后走。

                b.如果不相同,回到第1步,继续入栈,然后比较。知道pushV入完。下面是不相同:

结束条件:
        遍历pushV有俩种结果:
1.遍历完pushV,popV结束,st为空

2.遍历往pushV,st不为空,popV没走完。

代码:

class Solution {
public:bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {// write code heresize_t popi = 0, pushi = 0;stack<int> s;for(; pushi < pushV.size(); pushi++){//先入一个s.push(pushV[pushi]);//进行比较while(!s.empty() && s.top() == popV[popi]){//如果出栈和popV匹配,则s出栈,比较下一个出栈的。popi++;s.pop();}//如果不匹配//接着入栈}//结束条件,俩种结果都要遍历完pushV。//最后可以判断st是否为空。或者popi是否等于出栈序列的大小return s.empty();//return popi == popV.size();}
};

3.二叉树的层序遍历


102. 二叉树的层序遍历 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/binary-tree-level-order-traversal/description/二叉树的层序遍历要使用到队列。

class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {queue<TreeNode*> q;q.push(root);//插入头节点while(!q.empty()){//头节点出TreeNode* front = q.front();q.pop();//孩子节点入.不为空再入if(front->left)q.push(front->left);if(front->right)q.push(front->right);}}
};

思路:使用一个levesize变量控制一层一层出。

第一层:1个数据。

levesize = 1;

第一层出完之后:

下一层的个数是q.size();

重置levesize = q.size();

第二层是:第一层孩子的个数。
所以控制levesize--。就可以将每一层的储存到二维数组里。

class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> vv;if(root == nullptr){return vv;}queue<TreeNode*> q;q.push(root);//插入头节点int levelsize = 1;while(!q.empty()){vector<int> v;while(levelsize--){ //头节点出TreeNode* front = q.front();q.pop();//将这一层的值存储到一维数组里v.push_back(front->val);//孩子节点入.不为空再入if(front->left)q.push(front->left);if(front->right)q.push(front->right);}vv.push_back(v);//下一层的个数是q.size()levelsize = q.size();   }return vv;}
};

三、stack和queue的模拟实现

        1.stack的模拟实现

从栈的接口中可以看出,栈实际是一种特殊的vector,因此使用vector完全可以模拟实现stack。

#include<vector>
namespace mystack
{template<class T>class stack{public:stack() {};void push(const T& x) {_c.push_back(x);}void pop() {_c.pop_back();}T& top() {return _c.back();}const T& top()const {return _c.back();}size_t size()const {return _c.size();}bool empty()const {return _c.empty();}private:std::vector<T> _c;};
}

        像上面这样修改起来不方便,可以增加模板参数:

#include <iostream>
using namespace std;
#include <vector>
#include <list>
#include <deque>
namespace mystack
{template<class T, class Container = vector<T>>class stack{public:stack(){};//入栈void push(const T& data){_con.push_back(data);}//出栈void pop(){_con.pop_back();}//栈顶数T top(){return _con.back();}//判空bool empty(){return _con.empty();}//数据size_t size(){return _con.size();}private:Container _con;};
}

2.queue的模拟实现

        因为queue的接口中存在头删和尾插,因此使用vector来封装效率太低,故可以借助list来模拟实现queue,具体如下:

#include <iostream>
using namespace std;
#include <vector>
#include <list>
#include <deque>namespace myqueue {template<class T, class Container = list<T> > class queue{public:queue() {};//插入void push(const T& data){_con.push_back(data);}//popvoid pop(){_con.pop_front();}T& front(){return _con.front();}T& back(){return _con.back();}const T& front(){return _con.front();}	const T& back(){return _con.front();}//emptybool empty(){return _con.empty();}//sizesize_t size(){return _con.size();}private:Container _con;};
}

如果你有所收获,可以留下你的点赞和关注。谢谢你的观看!!!

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

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

相关文章

强达电路营收下滑净利润急剧放缓:周转率骤降,2次因环保被罚

《港湾商业观察》施子夫 自2022年6月向深交所创业板递交招股书起&#xff0c;深圳市强达电路股份有限公司&#xff08;以下简称&#xff0c;强达电路&#xff09;已收到深交所下发的两轮审核问询函&#xff0c;并且公司已于2023年3月31日顺利过会。但由于迟迟未提交注册申请&a…

无实验数据指导蛋白质定向进化,上海交大洪亮课题组发表微环境感知图神经网络 ProtLGN

在现代生物技术和医药研究中&#xff0c;蛋白质工程扮演着至关重要的角色。通过修改蛋白质的氨基酸序列&#xff0c;蛋白质工程可以改善或赋予蛋白质新的生物化学性质&#xff0c;如增强酶的催化效率、提高药物的亲和力或改善其热稳定性。这些改进对于开发新药、治疗疾病以及提…

lua vm 一: attempt to yield across a C-call boundary 的原因分析

使用 lua 的时候有时候会遇到这样的报错&#xff1a;“attempt to yield across a C-call boundary”。 1. 网络上的解释 可以在网上找到一些关于这个问题的解释。 1.1 解释一 这个 issue&#xff1a;一个关于 yield across a C-call boundary 的问题&#xff0c;云风的解释是…

【最新鸿蒙应用开发】——实用广告思路,可动态修改(方便运营)

鸿蒙项目加入广告展示页业务 广告页的思路——华为有广告业务&#xff0c;但是我们不用- ad模块&#xff1b; 想自定义广告——场景&#xff1a; app启动-有广告需求&#xff0c;就打开广告页&#xff0c;没有的话就去登录或者主页&#xff1b; 腾讯体育的广告- 启动有广告页…

适合小白学习的项目1894java开发ssm框架校园跑腿管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java ssm 校园跑腿管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采…

Java项目:96 springboot精品在线试题库系统

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 这次开发的精品在线试题库系统有管理员&#xff0c;教师&#xff0c;学生三个角色。 管理员功能有个人中心&#xff0c;专业管理&#xff0c;学生管理…

比较(二)利用python绘制雷达图

比较&#xff08;二&#xff09;利用python绘制雷达图 雷达图&#xff08;Radar Chart&#xff09;简介 雷达图可以用来比较多个定量变量&#xff0c;也可以用于查看数据集中变量的得分高低&#xff0c;是显示性能表现的理想之选。缺点是变量过多容易造成阅读困难。 快速绘制…

网站入门:Flask用法讲解

Flask是一个使用Python编写的轻量级Web服务框架&#xff0c;旨在帮助开发人员快速构建和部署Web应用程序。下面将对Flask进行更为详细的解释说明&#xff0c;并展示其使用示例与注意事项&#xff1a; 1.解释说明 定义及特点: Flask以其简洁和灵活著称&#xff0c;允许开发者以…

C++:list模拟实现

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《C&#xff1a;list模拟实现》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 如果本篇文章对你有帮助&#xff0c;还请各位点点赞&#xff01;&#xf…

LeetCode题练习与总结:二叉树展开为链表--114

一、题目描述 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。 …

格式化数据恢复指南:从备份到实战,3个技巧一网打尽

朋友们&#xff01;你们有没有遇到过那种“啊&#xff0c;我的文件呢&#xff1f;”的尴尬时刻&#xff1f;无论是因为手滑、电脑抽风还是其他原因&#xff0c;数据丢失都可能会让我们抓狂&#xff0c;甚至有时候&#xff0c;我们可能一不小心就把存储设备格式化了&#xff0c;…

香橙派OrangePI AiPro测评 【运行qt,编解码,xfreeRDP】

实物 为AI而生 打开盒子 配置 扛把子的 作为业界首款基于昇腾深度研发的AI开发板&#xff0c;Orange Pi AIpro无论在外观上、性能上还是技术服务支持上都非常优秀。采用昇腾AI技术路线&#xff0c;集成图形处理器&#xff0c;拥有8GB/16GB LPDDR4X&#xff0c;可以外接32…

进程通信——管道

什么是进程通信&#xff1f; 进程通信是实现进程间传递数据信息的机制。要实现数据信息传递就要进程间共享资源——内存空间。那么是哪块内存空间呢&#xff1f;进程间是相互独立的&#xff0c;一个进程不可能访问其他进程的内存空间&#xff0c;那么这块空间只能由操作系统提…

【全开源】简单商城系统源码(PC/UniAPP)

提供PC版本、UniAPP版本(高级授权)、支持多规格商品、优惠券、积分兑换、快递鸟电子面单、支持移动端样式、统计报表等 提供全部前后台无加密源代码、数据库离线部署。 构建您的在线商店的基石 一、引言&#xff1a;为什么选择简单商城系统源码&#xff1f; 在数字化时代&am…

【Spring Cloud Alibaba】初识Spring Cloud Alibaba

目录 回顾主流的微服务框架Spring Cloud 版本简介Spring Cloud以往的版本发布顺序排列如下&#xff1a; 由停更引发的"升级惨案"哪些Netflix组件被移除了&#xff1f; 替换方案服务注册中心&#xff1a;服务调用&#xff1a;负载均衡&#xff1a;服务降级&#xff1a…

干货分享 | TSMaster 中 Hex 文件编辑器使用详细教程

TSMaster 软件的 Hex 文件编辑器提供了文件处理的功能&#xff0c;这一特性让使用 TSMaster 软件的用户可以更便捷地对 Hex、bin、mot、s19 和 tsbinary 类型的文件进行处理。 本文重点讲述 TSMaster 中 Hex 文件编辑器的使用方法&#xff0c;该编辑器能实现将现有的 Hex、bin、…

@vue-office/excel 解决移动端预览excel文件触发软键盘

先直接上代码 不耽误大家时间 标明下插件库 非常感谢作者提供预览插件 vue-office/excel 只需要控制CSS :deep(.x-spreadsheet-overlayer) {.x-spreadsheet-selectors {display: none !important;} } :deep(.x-spreadsheet-bottombar) {li.active {user-select: none !import…

家政上门系统源码,家政上门预约服务系统开发涉及的主要功能

家政上门预约服务系统开发是指建立一个在线平台或应用程序&#xff0c;用于提供家政服务的预约和管理功能。该系统的目标是让用户能够方便地预约各种家政服务&#xff0c;如保洁、家庭护理、月嫂、家电维修等&#xff0c;并实现服务供应商管理和订单管理等功能。 以下是开发家政…

linux驱动学习(三)之uboot与内核编译

需要板子一起学习的可以这里购买&#xff08;含资料&#xff09;&#xff1a;点击跳转 GEC6818内核源码下载&#xff1a;点击跳转 一、环境配置 由于GEC6818对应是64位系统&#xff0c;虚拟机中的linux系统也要是64位&#xff0c;比如&#xff1a;ubuntu16.04.rar …

某红书旋转滑块验证码分析与协议算法实现(高通过率)

文章目录 1. 写在前面2. 接口分析3. 验证轨迹4. 算法还原 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致…