news 2026/8/30 23:22:57

STL中的stack和queue介绍及模拟实现(C++)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STL中的stack和queue介绍及模拟实现(C++)

stack

stack指的是栈,它的机制是后进先出或先进后出

stack的接口

push()栈顶入数据
pop()栈顶出数据
stack()建立一个空栈
size()获取有效数据个数
empty()判断栈是否为空
top()获取栈顶数据

stack的模拟实现

在模拟实现我们先引入一个问题,stack可以用哪些数据结构(string、vector、list、queue、deque(deque是双端队列,是vector和list的结合,顾名思义,双端均可实现效率较高的插入删除,还可以实现下标访问))高效实现?queue可以用哪些数据结构高效实现?

既然stack和queue的底层是用这些数据结构来实现,我们引入容器适配器概念,容器适配器是将一个类的接口转换成客户希望的另外一个接口,就如stack和queue底层是其他数据结构,但我们调用stack和queue时把它们作为一种数据结构,实现了转换。那么如何实现呢?在设计stack和queue的模板时增添一个模板参数,让它作为stack和queue的底层数据结构,再在底层上实现stack和queue的功能。C++还实现了模板参数缺省的功能,如下

那么我们为什么要让deque作为stack和queue默认的底层呢?

stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性 结构,都可以作为stack的底层容器,比如vector和list都可以;queue是先进先出的特殊线性数据 结构,只要具有push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如 list。但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作

在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高

结合了deque的优点,而完美的避开了其缺陷

deque总结

deque结合了vector和list的优点,但相比vector和list优点都不够极致

vectorlistdeque
优点

1.尾插尾删效率高

2.随机访问速度快

3.cpu高速缓存命中率高

1.任意位置插入删除效率高

2.仅插入删除当前迭代器失效

3.扩容不需要拷贝旧数据,不存在容量概念

1.头部尾部插入删除效率都高

2.cpu高速缓存命中率较高

3.支持随机访问,但效率不如vector

4.扩容不需要拷贝旧数据

缺点

1.头部以及中间插入删除效率低

2.扩容可能要复制旧数据

1.cpu高速缓存命中率低

2.随机访问效率低

1.中间位置插入删除效率低

2.内部结构较复杂,迭代器开销大

queue

queue是队列,是一种容器适配器,机制是先进先出

queue的接口

queue()构造空队列
empty()判断是否为空
size()获取有效数据个数
front()获取队头元素
back()获取队尾元素
push()队尾入数据
pop()队头出数据

queue的模拟实现

priority_queue

优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的,由此可以想到它的底层是堆,而堆的底层可以是vector和deque,默认数据结构为vector,因为其所需操作vector均可胜任,而vector结构简单,开销小。

因此priority_queue就是堆,所有考虑用到堆的地方,都可以考虑priority_queue,但要注意默认情况下priority_queue是大堆

priority_queue的接口

priority_queue()/priority_queue(first,last)构造一个优先级队列(空/复制另一个容器的数据)
empty()判断是否为空
top()返回堆顶元素,即优先级队列的最大(最小)元素
push()优先级队列插入元素
pop()删除堆顶元素,即优先级队列的最大(最小)元素

priority_queue的模拟实现

在模拟实现之前引入仿函数概念,其实就是用类中的成员函数operator(),其形式与函数十分相像,但语义不同(匿名对象(也可以是有名对象)调用operator()函数)

sort(v.begin(),v.end(),std::greater<int>());//greater<int>()即为仿函数

其设计目的是弥补函数指针的缺陷

上图模板参数中的第三个是用来控制priority_queue是大堆还是小堆,如果传函数指针,这样Compare仅仅只是函数指针类型,无法实例化发挥其作用。仿函数可以直接用来比较,也可以根据需求来控制比较逻辑(如一个类内部未实现比较,可以通过仿函数内部代码来实现比较逻辑),还有更多场景我们以后还会遇到

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 23:22:38

STM32L071启动失败排查指南:从电源、复位到选项字节的深度解析

1. 上电瞬间的“三秒定律”&#xff1a;现象决定你该往哪个方向查拿到一块 STM32L071 的板子&#xff0c;报告“Bootup fails”&#xff0c;这其实不是一个有用的信息。它就像说“车开不动”一样&#xff0c;可能是没油、没电、挂了空挡&#xff0c;也可能是发动机直接报废。我…

作者头像 李华
网站建设 2026/8/30 23:20:18

OpenAI回购与高管离场:开发者如何用工程手段降低大模型API依赖

1. 一个信号&#xff1a;回购、离场与 AI 巨头的不确定性最近有一条新闻在科技圈里引发了不少讨论&#xff1a;OpenAI 被曝出正在开展一笔规模相当大的股票回购&#xff0c;涉及资金量达到数百亿美元级别&#xff0c;与此同时&#xff0c;又有高管被曝选择离场。很多人的第一反…

作者头像 李华
网站建设 2026/8/30 23:19:43

把电话能力无缝嵌入企业自有CRM

做企业电销和客户运营落地这么久&#xff0c;发现绝大多数企业都有自己成熟的CRM客户管理系统&#xff0c;日常线索录入、客户跟进、数据统计、客户台账管理&#xff0c;团队早就习惯在自有系统里完成整套工作流程。 但几乎所有公司都会遇到同一个落地痛点&#xff1a;自研或商…

作者头像 李华
网站建设 2026/8/30 23:18:41

CVE-2026-65641 Veeam ONE漏洞实战检测、入侵溯源与彻底加固教程

0. 前置导读&#xff1a;为什么这个漏洞必须零窗口期处置 绝大多数企业的内网安全防护重心&#xff0c;都集中在边界防火墙、Web应用、办公终端这些常规资产上&#xff0c;长期忽略备份基础设施的安全权重。这也是近年勒索攻击的核心打法&#xff1a;不优先攻破业务系统&#x…

作者头像 李华
网站建设 2026/8/30 23:18:25

OLED 显示屏——让 Arduino 拥有自己的“屏幕“

前面我们学了舵机、超声波、红外遥控&#xff0c;Arduino 已经能"动"、能"看"、能"遥控"了。但有个问题一直没解决——所有数据只能靠串口监视器看&#xff0c;你得连电脑才能知道 Arduino 在干什么。今天这篇&#xff0c;我们要给 Arduino 装上…

作者头像 李华
网站建设 2026/8/30 23:18:11

自动售货机NFC支付模块集成实战:从硬件选型到交易流程的工程实践

在自动售货机从“投币出货”向“无感支付”演进的过程中&#xff0c;NFC非接触支付正在成为智能售货机的标配功能。用户只需将手机或银行卡靠近设备&#xff0c;即可完成支付&#xff0c;全程无需扫码、无需输入密码。但NFC模块的集成涉及硬件选型、通信协议、安全认证等多个环…

作者头像 李华