当前位置: 首页 > news >正文

【C++】—— stack和queue的模拟实现

前言

stackqueue使用起来都非常简单,现在来模拟实现一下,理解其底层的原理。


​ 在实现之前,应该知道,stackqueue 都是容器适配器,通过看官网文件也可以看出来;其默认的容器都是deque(双端队列)。

stackqueue 都是在容器的基础上进行了封装,实现了各自的操作。

(在下面的实现中stack默认容器用vectorqueue默认容器用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();}

frontback

​ 返回队头数据 / 队尾数据

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);}

​ 到这里stackqueue的模拟实现就完成了,感觉是不是很容易呢。

三、双端队列(deque)的栈和队列操作

deque(双端队列)既可以当作栈,也可以当作队列使用。我们可以在双端队列的两端进行插入和删除操作,从而更灵活地实现栈和队列的功能。

对于双端队列,简单来说,就是可以像vector那样随机访问,也可以像链表那样随机位置插入;但是,效率很低,(个人感觉,就是为了给stackqueue作默认容器适配器来用的。

这里就不过多描述双端队列了,感兴趣可以去看一下源码学习学习。

继续加油!!!

_con.size();
}


**`swap`**~~~cppvoid swap(Container& con){_con.swap(con);}

​ 到这里stackqueue的模拟实现就完成了,感觉是不是很容易呢。

三、双端队列(deque)的栈和队列操作

deque(双端队列)既可以当作栈,也可以当作队列使用。我们可以在双端队列的两端进行插入和删除操作,从而更灵活地实现栈和队列的功能。

对于双端队列,简单来说,就是可以像vector那样随机访问,也可以像链表那样随机位置插入;但是,效率很低,(个人感觉,就是为了给stackqueue作默认容器适配器来用的。

这里就不过多描述双端队列了,感兴趣可以去看一下源码学习学习。

继续加油!!!

相关文章:

【C++】—— stack和queue的模拟实现

前言 ​ stack 和 queue使用起来都非常简单&#xff0c;现在来模拟实现一下&#xff0c;理解其底层的原理。 ​ 在实现之前&#xff0c;应该知道&#xff0c;stack 和 queue 都是容器适配器&#xff0c;通过看官网文件也可以看出来&#xff1b;其默认的容器都是deque&#xff…...

管家婆工贸ERP BR039.采购订单关联MRP明细表

最低适用版本&#xff1a; 工贸系列 23.8 插件简要功能说明&#xff1a; 采购订单明细表&#xff0c;支持显示采购订单明细上游请购单明细关联的MRP中对应销售订单明细产成品相关信息更多细节描述见下方详细文档 插件操作视频&#xff1a; 进销存类定制插件--采购订单关联M…...

SwanLab安装教程

SwanLab是一款开源、轻量级的AI实验跟踪工具&#xff0c;提供了一个跟踪、比较、和协作实验的平台&#xff0c;旨在加速AI研发团队100倍的研发效率。 其提供了友好的API和漂亮的界面&#xff0c;结合了超参数跟踪、指标记录、在线协作、实验链接分享、实时消息通知等功能&…...

MySQL EXPLAIN,数据库调优的秘密通道

EXPLAIN 是 MySQL 中一个非常有用的工具&#xff0c;它用于分析 SQL 查询的执行计划。通过 EXPLAIN&#xff0c;你可以获取 MySQL 是如何准备执行你的 SQL 语句的&#xff0c;包括使用的索引、连接类型、扫描的行数等信息。这些信息对于优化查询性能、识别性能瓶颈至关重要。 使…...

利用redis的key失效监听器KeyExpirationEventMessageListener作任务定时提醒功能

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

如何基于Tesseract实现图片的文本识别

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

JavaWeb之AJAX

前言 这一节讲JavaWeb之AJAX 1.概述 以前我们在servlet中得到数据&#xff0c;必须通过域给jsp&#xff0c;然后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.输入命令扩容 如上终端中的代码解释&#xff1a; D:\Program Files\Oracle\VirtualBox>.\VBoxManage modifyhd D:\ubuntu18.04\Ubuntu18.04\Ubuntu18.04.vdi --resize 40960如上代码说明&#xff1a;D:\Program Files\Oracle\Virtual…...

RabbitMQ教程:路由(Routing)(四)

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

华为Ensp模拟器配置RIP路由协议

目录 RIP路由详解&#xff1a;另一种视角解读 1. RIP简介&#xff1a;轻松理解基础概念 2. RIP的核心机制&#xff1a;距离向量的魅力 3. RIP的实用与局限 RIP配置实验 实验图 ​编辑 PC的ip配置 RIP配置步骤 测试 结语&#xff1a;RIP的今天与明天 RIP路由详解&…...

3. langgraph中的react agent使用 (在react agent添加系统提示)

环境准备 确保你已经安装了以下库&#xff1a; langchainlangchain_openailanggraph 你可以使用以下命令进行安装&#xff1a; pip install langchain langchain_openai langgraph代码实现 1. 初始化模型 首先&#xff0c;我们需要初始化智谱AI的聊天模型。 from langch…...

(02)ES6教程——Map、Set、Reflect、Proxy、字符串、数值、对象、数组、函数

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

【快速解决】kafka崩了,重启之后,想继续消费,怎么做?

目录 一、怎么寻找我们关心的主题在崩溃之前消费到了哪里&#xff1f; 1、一个问题&#xff1a; 2、查看消费者消费主题__consumer_offsets 3、一个重要前提&#xff1a;消费时要提交offset 二、指定 Offset 消费 假如遇到kafka崩了&#xff0c;你重启kafka之后&#xff0…...

C++ 的发展

目录 C 的发展总结&#xff1a;​编辑 1. C 的早期发展&#xff08;1979-1985&#xff09; 2. C 标准化过程&#xff08;1985-1998&#xff09; 3. C 标准演化&#xff08;2003-2011&#xff09; 4. C11&#xff08;2011年&#xff09; 5. C14&#xff08;2014年&#xf…...

RabbitMQ 高级特性——延迟队列

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

‌EAC(Estimate at Completion)和ETC(Estimate to Complete)

‌EAC 预计完工成本ETC 预计尚需成本Estimate at CompletionEstimate to Complete完成预估完工时尚需成本估算 EAC ETC ACETC EAC – AC 预测项目总成本&#xff0c;包含了到目前为止实际发生的成本&#xff08;AC&#xff09;和预计将发生的成本。如果EAC大于BAC&#xf…...

【React】状态管理之Zustand

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 状态管理之Zustand引言1. Zustand 的核心特点1.1 简单直观的 API1.2 无需 Provi…...

Vue3打包自动生成版本JSON文件,添加系统版本检查,实现系统自动更新提示

实现该功能一共有三步。废话不多说&#xff0c;直接上代码&#xff01;&#xff01;&#xff01; 第一步&#xff1a;打包时自动生成版本信息的js文件&#xff0c;versionUpdate.js import fs from fs; import path from path; import { ElMessageBox } from element-plus; i…...

ROS导航避坑指南:搞清rviz里‘2D Pose Estimate’和‘2D Nav Goal’的区别与正确使用姿势

ROS导航避坑指南&#xff1a;rviz中‘2D Pose Estimate’与‘2D Nav Goal’的深度解析与实践技巧 在机器人操作系统&#xff08;ROS&#xff09;的导航栈开发中&#xff0c;rviz作为可视化调试的核心工具&#xff0c;其2D Pose Estimate和2D Nav Goal两个功能按钮看似简单&…...

ARM SMMU-700内存管理单元原理与优化实践

1. MMU-700 SMMU架构概述与典型应用场景内存管理单元&#xff08;MMU&#xff09;是现代计算机系统中不可或缺的核心组件&#xff0c;负责处理虚拟地址到物理地址的转换。在ARM架构中&#xff0c;系统级内存管理单元&#xff08;SMMU&#xff09;扮演着更为关键的角色&#xff…...

Flink窗口实战避坑指南:从AggregateFunction到ProcessWindowFunction,我踩过的那些坑

Flink窗口实战避坑指南&#xff1a;从AggregateFunction到ProcessWindowFunction的深度解析 第一次在真实项目中使用Flink窗口时&#xff0c;我像发现新大陆一样兴奋。直到凌晨三点被报警短信惊醒&#xff0c;才发现窗口计算的结果完全偏离预期——这让我意识到&#xff0c;窗口…...

ArcSWAT建模踩坑记:你的土壤数据库参数算对了吗?聊聊SPAW的那些默认值和单位陷阱

ArcSWAT土壤参数校准实战&#xff1a;避开SPAW计算中的5个致命误区 当水文模拟结果与实测数据出现系统性偏差时&#xff0c;经验丰富的建模者会首先检查土壤参数——这个隐藏在界面背后的"沉默变量"往往是误差的最大来源。SPAW作为ArcSWAT推荐的土壤参数计算工具&…...

如何高效构建视频数据集:video2frame终极实战指南

如何高效构建视频数据集&#xff1a;video2frame终极实战指南 【免费下载链接】video2frame Yet another easy-to-use tool to extract frames from videos, for deep learning and computer vision. 项目地址: https://gitcode.com/gh_mirrors/vi/video2frame 在计算机…...

GEO优化实操框架:GEO优化的正确姿势是“带着答案去找客户”

如果你是B2B企业的老板或市场负责人&#xff0c;你一定听过这句话&#xff1a; “我们网上曝光是不少&#xff0c;但来的询盘都不对——问价格的比问方案的还多&#xff0c;还有不少是学生做调研的。” 这不是你一个人遇到的问题。这是传统SEO和竞价广告的天然缺陷——你只能“…...

智慧树自动刷课终极指南:3分钟快速上手Autovisor免费工具

智慧树自动刷课终极指南&#xff1a;3分钟快速上手Autovisor免费工具 【免费下载链接】Autovisor 2025智慧树刷课脚本 基于Python Playwright的自动化程序 [有免安装版] 项目地址: https://gitcode.com/gh_mirrors/au/Autovisor 还在为智慧树网课的手动操作烦恼吗&#…...

深入Transformer内部:LoRA到底改动了哪部分权重才让模型“学会”新任务?

深入Transformer内部&#xff1a;LoRA如何通过低秩更新重塑大模型能力 在自然语言处理领域&#xff0c;大型预训练模型的微调一直是个计算密集型任务。传统全参数微调需要更新数十亿甚至数千亿参数&#xff0c;这对大多数研究者和企业来说都是难以承受的负担。低秩适应(LoRA)技…...

告别网络依赖:CircuitJS1桌面版带你体验离线电路仿真的自由

告别网络依赖&#xff1a;CircuitJS1桌面版带你体验离线电路仿真的自由 【免费下载链接】circuitjs1 Standalone (offline) version of the Circuit Simulator with small modifications based on modified NW.js. 项目地址: https://gitcode.com/gh_mirrors/circ/circuitjs1…...

AI驱动命令行工具:用自然语言自动化开发任务

1. 项目概述&#xff1a;一个为开发者“下厨”的AI助手如果你是一名开发者&#xff0c;每天在终端里敲打命令&#xff0c;构建、部署、调试&#xff0c;那么你肯定对重复性的命令行操作感到厌倦。比如&#xff0c;每次启动一个新项目&#xff0c;都要手动创建目录结构、初始化G…...