C++stack和queue模拟实现以及deque的介绍
stack和queue介绍以及模拟实现
- 1.stack
- 1.1stack的介绍
- 1.2stack的使用
- 2.queue
- 2.1queue的介绍
- 2.2queue的使用
- 3.容器适配器
- 3.1什么是适配器
- 4.stack模拟实现
- 5.queue的模拟实现
- 6.deque(双端队列)
1.stack
1.1stack的介绍
stack的文档介绍
- stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,只能从容器的一端进行元素的插入与提取操作。
- stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。
- stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:
empty:判空操作
back:获取尾部元素操作
push_back:尾部插入元素操作
pop_back:尾部删除元素操作 - 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque。
1.2stack的使用
stack的接口现在看起来对于前面已经学过string,vector,list已经是很简单的了。
这里就不再对接口进行详细介绍。来写几道题对stack的接口有更熟悉的使用。
最小栈
思路一
这道题大部分人的思路,可能是这样的,再申请一个变量,每次都和插入的数据进行比较,如果比新插入的数据小就更新。
思路二
申请两个栈,其中一个栈记录,插入最小的元素。
会初始化的,那为什么会初始化呢?
这个成员变量会走初始化列表,对内置类型不处理,对自定义类型调用它的构造函数。
那如果把这个Minstack()删掉,成员变量会不会初始化?
同样也是会的,系统默认生成的构造函数,对内置类型不处理,除非给内置类型缺省值,对自定义类型调用它的构造函数。
因此这里也没有析构函数。
class MinStack {
public:MinStack() {}void push(int val) {_min.push(val);//这里必须判空在前面,否则_count.top()会报错if(_count.empty() || _count.top() >= _min.top())_count.push(val);}void pop() {if(_count.top() == _min.top())_count.pop();_min.pop();}int top() {return _min.top();}int getMin() {return _count.top();}stack<int> _min;stack<int> _count;
};
JZ31 栈的压入、弹出序列
思路
这道题穷举是不可能的,
其实可以这样想,第一个是入栈序列,第二个是出栈序列,如果第一个的出栈序列可以和第二个出栈序列互相匹配,那不就是true了吗,不能匹配,return false;
这里就不再演示不匹配了,
写法1,返回条件以push1,pop1来进行判断。
class Solution {
public:bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {stack<int> _st;int i=0,j=0;_st.push(pushV[i++]);while(1){//相等就出栈if(!_st.empty() && _st.top() == popV[j]){_st.pop();++j;if(j == popV.size())return true;}//不相等/栈为空就入栈else {if(i == pushV.size() && j != popV.size() )return false;_st.push(pushV[i++]);}}}
};
写法2,返回条件以循环结构,st栈是否为空来判断
class Solution {
public:bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {stack<int> _st;size_t pop1=0;for(size_t push1=0;push1<pushV.size();++push1){_st.push(pushV[push1]);while(!_st.empty() &&_st.top() == popV[pop1]){_st.pop();++pop1;}}return _st.empty();}
};
150. 逆波兰表达式求值
逆波兰表达式,就在后缀表达式。
后缀转中缀思路
遇见操作数直接入栈,遇到运算符"+“,”-“,”*“,”/“,出栈,先出的是右操作数,这是因为”-“,”/",要分左右。然后把结果入栈。最后栈中剩下的元素就是最终结果。
class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> _st;for(auto& str : tokens){if(str == "+" || str == "-" || str == "*" || str == "/"){int right=_st.top();_st.pop();int left=_st.top();_st.pop();switch(str[0]){case '+':_st.push(left+right);break;case '-':_st.push(left-right);break;case '*':_st.push(left*right);break;case '/':_st.push(left/right);break;default:break;}}else{//字符串转为int,stoi函数_st.push(stoi(str));}}return _st.top();}
};
这里介绍一下C++把字符串变成各种类型的接口;
前面是把后缀变成中缀,这里再提供把中缀变成后缀的思路。
申请一个存放运算符的栈
1.操作数直接输出
2.栈空时,碰见运算符直接入栈,栈不空时,碰见运算符,需要外面运算符和栈顶的运算符比较。如果栈里面运算符优先级比外面的高或者相等,就一直出栈,直到栈空或者碰见优先级低于外面的运算符就停止。这个时候再把外面的运算符入栈。当遍历完之后,再把栈里面所有运算符依次出栈。
这个有兴趣可以写一下。
232. 用栈实现队列
提示:用两个栈。一个入栈,一个出栈。
2.queue
2.1queue的介绍
queue的文档介绍
- 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。
- 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。
- 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:
empty:检测队列是否为空
size:返回队列中有效元素的个数
front:返回队头元素的引用
back:返回队尾元素的引用
push_back:在队列尾部入队列
pop_front:在队列头部出队列 - 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。
2.2queue的使用
关于队列的题这里就不再讲解。
有兴趣可以写下面这道题
225. 用队列实现栈
提示:用两个队列。
3.容器适配器
3.1什么是适配器
适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。
其实到目前为止,我们已经接触了两种设计模式:
1.适配器模式
把已有的东西封装起来,转换出你想要的东西。
2.迭代器模式
不暴露底层实现细节,封装后提供统一的方式访问容器。
如果我们还是按照以往的想法,实现一个栈(如果是顺序栈),肯定是申请一个变长数组,一个size,一个capacity,再写一些成员函数。
template<class T>
class stack
{
public://成员函数
private:T* _a;size_t _size;size_t _capacity;
};
但是stack,queue都是适配器模式,我们可以不再自己写,而是可以用已有的东西封装起来,转换成自己想要的东西。
4.stack模拟实现
既然stack即可以用vector/list封装,因此模板我们给两个参数
#include<iostream>
#include<vector>
#include<list>
using namespace std;namespace bit
{template<class T,class container>class stack{public://自定义类型也可以不写构造stack() {};void push(const T& val){_con.push_back(val);}void pop(){_con.pop_back();}const T& top(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:container _con;};
}
发现stack的模拟实现就是这么简单。。。
stack用list封装也是没有问题。
有人可能会说不对啊,我自己使用的stack可没有你传参这么麻烦
这里解决方法给第二个容器参数一个缺省值就行了。
5.queue的模拟实现
namespace bit
{template<class T,class container=list<T>>class queue{public:queue() {};void push(const T& val){_con.push_back(val);}void pop(){_con.pop_front();}const T& front(){return _con.front();}const T& back(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:container _con;};
}
6.deque(双端队列)
deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。
但是deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组。
可能有人看了官方库发现,我们这里和库里面使用的容器不一样。
为什么库里面用的是deque(双端队列)
这里就不得不提到vector,list的缺点了
deque兼容了vector和list的优点
看起来deque这么好,那我们就只学这一种容器不就好了,还要学vector和list干吗,但是到现在我们还是在学vector和list,从这一方面就证明了,deque并不是那么完美。
deque底层结构
deque底层是由多个buffer数组,以及一个中控(指针数组)所组成。
deque这样的底层,才会即支持下标随机访问,又支持尾插尾删头插头删。
deque的缺点:
1.下标随机访问。
要算下标在第几个buffer,在这个buffer种第几个位置,因此下标随机访问有一定的时间消耗,不如vector快。
2.中间插入和删除。
也有一定的时间消耗,相比list中间插入删除不够极致,没有list快。
虽然deque有这些缺点,但是队友栈和队列是够用了。
那什么地方可以用deque(双端队列)呢?
中间插入和删除少,头尾插入删除多,偶尔下标随机访问。
相关文章:

C++stack和queue模拟实现以及deque的介绍
stack和queue介绍以及模拟实现 1.stack1.1stack的介绍1.2stack的使用 2.queue2.1queue的介绍2.2queue的使用 3.容器适配器3.1什么是适配器 4.stack模拟实现5.queue的模拟实现6.deque(双端队列) 1.stack 1.1stack的介绍 stack的文档介绍 stack是一种容…...
WPF ListView 鼠标点击,移动改变背景色不启作用
构建数据源 <Window.Resources><x:ArrayExtension x:Key"stringList"xmlns"clr-namespace:System;assemblymscorlib"Type"String"><String>第一行</String><String>第二行</String><String>第三行<…...
Maven Dependency 机制
依赖关系管理是Maven的核心功能。管理单个项目的依赖关系很容易。管理由数百个模块组成的多模块项目和应用程序的依赖关系是可能的。Maven在定义、创建和维护具有良好定义的类路径和库版本的可复制构建方面有很大帮助。 一、传递依赖 Maven通过自动包含可传递的依赖关系&…...

CustomShapes/自定义形状, CustomCurves/自定义曲线, AnimateableData/数据变化动画 的使用
1. CustomShapes 自定义形状视图 1.1 资源图文件 therock.png 1.2 创建自定义形状视图 CustomShapesBootcamp.swift import SwiftUI/// 三角形 struct Triangle: Shape{func path(in rect: CGRect) -> Path {Path { path inpath.move(to: CGPoint(x: rect.midX, y: rect.mi…...

软件测试用例设计方法-因果图法
边界值法是等价类划分法的补充,所以,它们是一对搭档。 那么,判定表法有没有它的搭档呢? 答案是,有的。那就是本篇文章分享的用例设计方法—— 因果图法 。 定义 因果图法: 用来处理等价类划分和边界值考…...

水库大坝安全监测是什么和主要作用?
水库大坝安全监测是指通过仪器观测和巡视检查对水利水电工程主体结构、地基基础、两岸边坡、相关设施以及周围环境所作的测量及观察。大坝安全监测是作为水库大坝安全管理的重要组成部分,是掌握水库大坝安全性态的重要手段,是科学调度、安全运行的前提。…...

极品三国新手攻略之进阶篇
尊敬的主公大人您好,首先恭喜您在游戏中取得的不俗成绩,相信您已经熟练掌握了不少玩法。今天,我们给大家奉上一份极品三国新手攻略之进阶篇,希望能为您提供有力的帮助。本篇攻略将为您深入分析游戏中武将、装备、试炼塔以及神兵等…...

windows应用程序告警:帐户名与安全标识间无任何映射完成
目录 一、问题现象 二、问题解决 (一)官方方法 (二)问题定位 (三)问题处理 一、问题现象 今天巡检域控服务器时,发现告警如下: 安全策略已传播,但有警告信息。 0x534…...

自定义jenkins镜像提示FontConfiguration.head错误
系统使用:Debian12,jdk17 提示问题:缺少字体 找一台jdk8的环境,在lib文件夹中找到fontconfig.bfc find / -name *fontconfig* 复制到jenkins目标服务器中,jdk目录的lib中 再次启动jenkins服务正常...

《软件方法》2023版第1章(10)应用UML的建模工作流-大图
DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 1.4 应用UML的建模工作流 1.4.1 概念 我用类图表示建模工作流相关概念如图1-16。 图1-16 建模工作流相关概念 图1-16左侧灰色部分定义了“游戏规则”,右侧则是在“游戏规…...

The given SOAPAction http__xxxxx_xx does not match an operation
这是在客户端调用服务端接口时报出的错误,主要是客户端在调用时设置了SOAPAction,参考如下: 解决方案 在注解WebMethod() 中加上action注解,设置上一模一样的SOAPAction即可,如下: WebMethod(action &qu…...

【java零基础入门到就业】第二天:jdk的下载安装和第一个HelloWorld程序
1、java内容概述 java前半部分学习内容主要如下: 1、Java基础语法2、面向对象3、API4、字符串5、集合6、拼图游戏 1.1、 java基础语法 java基础语法主要包括以下内容: Java入门小概念Idea和运算符判断和循环方法数组课后练习题 Java是什么…...

C++数据结构X篇_15_求二叉树叶子数与高度(递归方法)
本篇参考求二叉树叶子数与高度(C)进行整理。 文章目录 1. 二叉树中叶子数与高度2. 求二叉树叶子数与高度的实现代码 1. 二叉树中叶子数与高度 我们首先来看一看二叉树中叶子数与高度的定义: 叶子数:对于一个二叉树的节点&#x…...

MySQL锁学习笔记
锁 事务的隔离性由锁来实现。 概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在程序开发中会存在多线程同步的问题,当多个线程并发访问某个数据的时候,尤其是针对一些敏感的数据(比如订单、金额等),我…...

如何将前后端分离项目部署到本地的Docker Desktop容器运行并且访问
文章目录 前言 完成了客户的一个前后端分离项目,要求部署到客户电脑上去展示,那肯定不能直接把代码弄上去跑呀~~~,于是我就想把他们都打包部署到本地的docker容器里面,方便运行和访问,so,以下内容就详细介…...

前端开发中的try...catch
首先try...catch 结构可以用来处理 Promise 中的异常。在 JavaScript 中,Promise 提供了一种处理异步操作的机制,并且可以通过 .catch() 方法捕获并处理异步操作中抛出的异常。 async function someAsyncFunction() {try {const result await someProm…...

数据加密中,采用密钥管理系统相比加密机的好处
密钥管理系统与加密机都能提供数据加解密,那么针对具体的应用加密,采用密钥管理系统比单纯使用加密机有哪些优点,列表如下: 集中化管理:密钥管理系统可以对加密算法和密钥进行集中化管理,使得企业可以对加…...

Elasticsearch:什么是大语言模型 (LLMs)?
假设你想参加流行的游戏节目 Jeopardy(这是一个美国电视游戏节目,参赛者将获得答案并必须猜测问题)。 要参加演出,你需要了解任何事情的一切。 所以你决定在接下来的三年里每天都花时间阅读互联网上的所有内容。 你很快就会意识到…...
神奇的python的生成器
函数生成器代码 def num():print("message 1")yield 1print("message 2")yield 2print("message 3")yield 3f num() x next(f) # message 1 print(x) # 输出1x next(f) # message 2 print(x) # 输出2x next(f) # message 3 print(x) …...

【来点小剧场--项目测试报告】个人博客项目自动化测试
前述 针对个人博客项目进行测试,个人博客主要由七个页面构成:注册页、登录页、个人博客列表页、博客发布页、博客修改页、博客列表页、博客详情页,主要功能包括:注册、登录、编辑并发布博客、修改已发布的博客、查看详情、删除博…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...
Java多线程实现之Runnable接口深度解析
Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...

C++11 constexpr和字面类型:从入门到精通
文章目录 引言一、constexpr的基本概念与使用1.1 constexpr的定义与作用1.2 constexpr变量1.3 constexpr函数1.4 constexpr在类构造函数中的应用1.5 constexpr的优势 二、字面类型的基本概念与使用2.1 字面类型的定义与作用2.2 字面类型的应用场景2.2.1 常量定义2.2.2 模板参数…...

【技巧】dify前端源代码修改第一弹-增加tab页
回到目录 【技巧】dify前端源代码修改第一弹-增加tab页 尝试修改dify的前端源代码,在知识库增加一个tab页"HELLO WORLD",完成后的效果如下 [gif01] 1. 前端代码进入调试模式 参考 【部署】win10的wsl环境下启动dify的web前端服务 启动调试…...