【C++】—— stack和queue的模拟实现
前言
stack
和 queue
使用起来都非常简单,现在来模拟实现一下,理解其底层的原理。
在实现之前,应该知道,stack
和 queue
都是容器适配器,通过看官网文件也可以看出来;其默认的容器都是deque
(双端队列)。
stack
和 queue
都是在容器的基础上进行了封装,实现了各自的操作。
(在下面的实现中stack
默认容器用vector
,queue
默认容器用list
)
栈和队列的使用
栈的使用
首先,STL中的栈是基于容器适配器实现的,默认容器是deque。
使用栈需要包含头文件:
#include<stack>
1.1 栈的基本操作
先看一下,栈提供的接口函数
常用方法:
push()
: 将元素val
压入栈顶。pop()
: 移除栈顶元素。top()
: 返回栈顶元素(但不移除)。empty()
: 判断栈是否为空。size()
: 返回栈的元素数量。
1.2 栈的使用
现在简单使用一下stack:
void test_stack() {//创建一个栈——存储整形stack<int> s; //入栈s.push(1);s.push(2);s.push(3);//栈中元素cout << "元素个数: " << s.size() << endl;//栈顶元素cout << "栈顶元素: " << s.top() << endl;//出栈s.pop();//依次输出栈中的数据while (!s.empty()) {cout << s.top() << " ";s.pop();}cout << endl;return 0;
}
输出结果:
元素个数: 3
栈顶元素: 3
2 1
1.3 应用实例:点击消除
栈可以用来解决括号匹配这一类的问题。
括号匹配之前已经做过了,这里来用栈做这样的一道题:点击消除_牛客题霸_牛客网
题目描述:
这题思路比较简单,就是遍历字符串时,不断入栈,出栈(字符串中字符与栈顶元素相等);最后输出即可。
需要注意的是:这里使用数组来模拟栈,方便输出
当然也可以使用栈,不过输出时顺序是反的,需要进行处理。
#include <iostream>
using namespace std;int main() {string str;cin>>str;string ret;for(auto ch: str){if(ret.size()==0||ret[ret.size()-1]!=ch){ret.push_back(ch);}else {ret.pop_back();}}if(ret.empty()){cout<<'0';return 0;}cout<<ret;return 0;
}
队列的使用
2.1 队列的基本操作
STL
中的队列(queue
)也是一种容器适配器,默认底层容器也是 deque
。
使用栈需要包含头文件:
#include<queue>
常用方法:
push()
: 将元素val
插入队尾。pop()
: 移除队头元素。front()
: 返回队头元素(不移除)。back()
: 返回队尾元素(不移除)。empty()
: 判断队列是否为空。size()
: 返回队列的元素数量。
2.2 队列的使用
简单使用一下队列:
void test_queue()
{//创建一个队列——存储整型queue<int> q;//入队列q.push(10);q.push(20);q.push(30);cout << "数据个数: " << q.size() << endl;cout << "队头元素: " << q.front() << endl;cout << "队尾元素: " << q.back() << endl;//出队列q.pop();cout << "队列中数据: ";while (!q.empty()) {cout << q.front() << " ";q.pop();}cout << endl;
}
输出结果:
数据个数: 3
队头元素: 10
队尾元素: 30
队列中数据: 20 30
栈和队列的模拟实现
stack
模拟
学习过初阶数据结构的栈,大概知道栈是怎么实现的,使用过STL里的stack
也知道具体哪些操作,这里就直接开始实现。
1.默认成员函数
对于默认成员函数,因为这里stack
是对容器的封装,所以那些构造函数、析构函数、赋值运算符重载等都不需要我们自己去实现,编译器默认生成的会去调用vector(容器)的默认成员函数。
template<class T, class Container = vector<T>>class stack{stack() {}private:Container _con;};
2.基本操作
栈的基本操作无疑就是,入栈、出栈、取栈顶元素、判断栈是否为空。
入栈:
直接调用容器vector
的尾插即可。
void push(const T& x){_con.push_back(x);}
出栈:
直接调用容器vector
的尾删
void pop(){_con.pop_back();}
取栈顶元素:
直接返回容器vector
的最后一个元素即可,即调用back()
函数
T& top(){return _con.back();}const T& top()const {return _con.back();}
判断是否为空:
调用容器的empty
函数即可
bool empty() const{return _con.empty();}
返回栈中元素个数:
size_t size() const {return _con.size();}
swap
直接调用容器的swap
函数即可。
void swap(stack& st){_con.swap(st._con);}
到这里 就简单实现了我们的stack
结构了,是不是感觉很简单呢?
template<class T, class Container = vector<T>>class stack{public:stack() {}void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}T& top(){return _con.back();}const T& top()const {return _con.back();}bool empty() const{return _con.empty();}size_t size() const {return _con.size();}void swap(Container& st){_con.swap(st._con);}private:Container _con;};
queue
模拟
默认成员函数
和stack
一样,我们不需要去实现它的默认成员函数,编辑器默认生成的就已经可以满足我们的需求了。
基本操作
push
入队列,在队尾插入
void push(const T& x){_con.push_back(x);}
pop
出队列,从头部删除
void pop(){_con.pop_front();}
front
和back
返回队头数据 / 队尾数据
T& back()
{return _con.back();
}
const T& back() const
{return _con.back();
}
T& front()
{return _con.front();
}
const T& front()const
{return _con.front();
}
empty
bool empty() const{return _con.empty();}
size
size_t size() const{return _con.size();}
swap
void swap(Container& con){_con.swap(con);}
到这里stack
和queue
的模拟实现就完成了,感觉是不是很容易呢。
三、双端队列(deque
)的栈和队列操作
deque
(双端队列)既可以当作栈,也可以当作队列使用。我们可以在双端队列的两端进行插入和删除操作,从而更灵活地实现栈和队列的功能。
对于双端队列,简单来说,就是可以像vector那样随机访问,也可以像链表那样随机位置插入;但是,效率很低,(个人感觉,就是为了给stack
和queue
作默认容器适配器来用的。
这里就不过多描述双端队列了,感兴趣可以去看一下源码学习学习。
继续加油!!!
_con.size();
}
**`swap`**~~~cppvoid swap(Container& con){_con.swap(con);}
到这里stack
和queue
的模拟实现就完成了,感觉是不是很容易呢。
三、双端队列(deque
)的栈和队列操作
deque
(双端队列)既可以当作栈,也可以当作队列使用。我们可以在双端队列的两端进行插入和删除操作,从而更灵活地实现栈和队列的功能。
对于双端队列,简单来说,就是可以像vector那样随机访问,也可以像链表那样随机位置插入;但是,效率很低,(个人感觉,就是为了给stack
和queue
作默认容器适配器来用的。
这里就不过多描述双端队列了,感兴趣可以去看一下源码学习学习。
继续加油!!!
相关文章:

【C++】—— stack和queue的模拟实现
前言 stack 和 queue使用起来都非常简单,现在来模拟实现一下,理解其底层的原理。 在实现之前,应该知道,stack 和 queue 都是容器适配器,通过看官网文件也可以看出来;其默认的容器都是dequeÿ…...
管家婆工贸ERP BR039.采购订单关联MRP明细表
最低适用版本: 工贸系列 23.8 插件简要功能说明: 采购订单明细表,支持显示采购订单明细上游请购单明细关联的MRP中对应销售订单明细产成品相关信息更多细节描述见下方详细文档 插件操作视频: 进销存类定制插件--采购订单关联M…...

SwanLab安装教程
SwanLab是一款开源、轻量级的AI实验跟踪工具,提供了一个跟踪、比较、和协作实验的平台,旨在加速AI研发团队100倍的研发效率。 其提供了友好的API和漂亮的界面,结合了超参数跟踪、指标记录、在线协作、实验链接分享、实时消息通知等功能&…...
MySQL EXPLAIN,数据库调优的秘密通道
EXPLAIN 是 MySQL 中一个非常有用的工具,它用于分析 SQL 查询的执行计划。通过 EXPLAIN,你可以获取 MySQL 是如何准备执行你的 SQL 语句的,包括使用的索引、连接类型、扫描的行数等信息。这些信息对于优化查询性能、识别性能瓶颈至关重要。 使…...

利用redis的key失效监听器KeyExpirationEventMessageListener作任务定时提醒功能
某需求: 要求在任务截止日期的前3天时,系统自动给用户发一条消息提醒。 用定时任务的话感觉很不舒服。间隔时间不好弄。不能精准卡到那个点。 由于系统简单,没有使用消息列队,也不能使用延时队列来做。 用Timer的话开销还挺大的&a…...

如何基于Tesseract实现图片的文本识别
在前一篇文章基础上,如何将报告图片中的文本解析出来,最近研究了基于Tesseract的OCR方案,Tesseract OCR是一个开源的OCR引擎,主要结合开源的tesseract和pytesseract,实现了jpg/png等格式图片文本识别,供大家…...

JavaWeb之AJAX
前言 这一节讲JavaWeb之AJAX 1.概述 以前我们在servlet中得到数据,必须通过域给jsp,然后jsp在响应给浏览器 纯html不能获取servlet返回数据 所以我们用jsp 但是现在我们可以同AJAX给返回数据了 我们可以在sevlet中直接通过AJAX返回给浏览器 html中的J…...

算法---解决“汉诺塔”问题
# 初始化步骤计数器 i 1 # 定义移动盘子的函数 def move(n, mfrom, mto): global i # 使用全局变量i来跟踪步骤 print("第%d步:将%d号盘子从%s->%s" % (i, n, mfrom, mto)) # 打印移动步骤 i 1 # 步骤计数器加1 #第一种方法 # 定义汉诺塔问题的递归…...

1-Equity-Transformer:求解NP-Hard Min-Max路由问题的顺序生成算法(AAAI-24)(完)(code)
文章目录 AbstractIntroduction问题表述Methodology多智能体位置编码公平上下文编码训练方案ExperimentsmTSP的性能评估mPDP的性能评估Related WorkConclusionAbstract 最小最大路由问题旨在通过智能体合作完成任务来最小化多个智能体中最长行程的长度。这些问题包括对现实世界…...

linux001.在Oracle VM VirtualBox中ubuntu虚拟系统扩容
1.打开终端切换到virtualBox安装目录 2.输入命令扩容 如上终端中的代码解释: D:\Program Files\Oracle\VirtualBox>.\VBoxManage modifyhd D:\ubuntu18.04\Ubuntu18.04\Ubuntu18.04.vdi --resize 40960如上代码说明:D:\Program Files\Oracle\Virtual…...

RabbitMQ教程:路由(Routing)(四)
文章目录 RabbitMQ教程:路由(Routing)(四)一、引言二、基本概念2.1 路由与绑定2.2 Direct交换机2.3 多绑定2.4 发送日志2.5 订阅 三、整合代码3.1 EmitLogDirectApp.cs3.2 ReceiveLogsDirectApp.cs3.3 推送所有和接收e…...

华为Ensp模拟器配置RIP路由协议
目录 RIP路由详解:另一种视角解读 1. RIP简介:轻松理解基础概念 2. RIP的核心机制:距离向量的魅力 3. RIP的实用与局限 RIP配置实验 实验图 编辑 PC的ip配置 RIP配置步骤 测试 结语:RIP的今天与明天 RIP路由详解&…...
3. langgraph中的react agent使用 (在react agent添加系统提示)
环境准备 确保你已经安装了以下库: langchainlangchain_openailanggraph 你可以使用以下命令进行安装: pip install langchain langchain_openai langgraph代码实现 1. 初始化模型 首先,我们需要初始化智谱AI的聊天模型。 from langch…...

(02)ES6教程——Map、Set、Reflect、Proxy、字符串、数值、对象、数组、函数
目录 前言 一、Map Maps 和 Objects 的区别 Map的迭代 forEach() Map对象的操作 二、Set Set 中的特殊值 三、Reflect 四、Proxy 五、字符串 六、数值 七、对象 八、数组 九、函数 参考文献 前言 一、Map Map 对象保存键值对。任何值(对象或者原始值) 都可以…...

【快速解决】kafka崩了,重启之后,想继续消费,怎么做?
目录 一、怎么寻找我们关心的主题在崩溃之前消费到了哪里? 1、一个问题: 2、查看消费者消费主题__consumer_offsets 3、一个重要前提:消费时要提交offset 二、指定 Offset 消费 假如遇到kafka崩了,你重启kafka之后࿰…...

C++ 的发展
目录 C 的发展总结:编辑 1. C 的早期发展(1979-1985) 2. C 标准化过程(1985-1998) 3. C 标准演化(2003-2011) 4. C11(2011年) 5. C14(2014年…...

RabbitMQ 高级特性——延迟队列
文章目录 前言延迟队列延迟队列的概念TTL 死信队列模拟延迟队列设置队列的 TTL设置消息的 TTL 延迟队列插件安装并且启动插件服务使用插件实现延迟功能 前言 前面我们学习了 TTL 和死信队列,当队列中的消息达到了过期时间之后,那么这个消息就会被死信交…...

EAC(Estimate at Completion)和ETC(Estimate to Complete)
EAC 预计完工成本ETC 预计尚需成本Estimate at CompletionEstimate to Complete完成预估完工时尚需成本估算 EAC ETC ACETC EAC – AC 预测项目总成本,包含了到目前为止实际发生的成本(AC)和预计将发生的成本。如果EAC大于BAC…...

【React】状态管理之Zustand
🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 💫个人格言: "如无必要,勿增实体" 文章目录 状态管理之Zustand引言1. Zustand 的核心特点1.1 简单直观的 API1.2 无需 Provi…...

Vue3打包自动生成版本JSON文件,添加系统版本检查,实现系统自动更新提示
实现该功能一共有三步。废话不多说,直接上代码!!! 第一步:打包时自动生成版本信息的js文件,versionUpdate.js import fs from fs; import path from path; import { ElMessageBox } from element-plus; i…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...