STL - stack 和 queue 及容器适配器模式的介绍
文章目录
- 1. stack 的介绍和使用
- 1.1 stack 的介绍
- 1.2 stack 的接口及使用
- 1.3 stack 的模拟实现
- 2. queue 的介绍和使用
- 2.1 queue 的介绍
- 2.2 queue 的接口及使用
- 2.3 queue 的模拟实现
- 3. priority_queue的介绍和使用
- 3.1 priority_queue 的介绍
- 3.2 priority_queue 的接口及使用
- 3.3 priority_queue 的模拟实现
- 4. 容器适配器
- 4.1 什么是适配器?
- 4.2 STL标准库中stack和queue的底层结构
- 4.3 deque 的简单介绍
- 4.3.1 deque 的原理介绍
- 4.3.2 deque 的缺陷
- 4.4 为什么选择deque作为stack和queue的底层默认容器
- 4.5 stack 和 queue 的模拟实现
- 4.5.1 stack 的模拟实现
- 4.5.2 queue 的模拟实现
1. stack 的介绍和使用
1.1 stack 的介绍
std::stack 是 C++ 标准库中的一种容器适配器(Container Adapter),它基于其他容器(如 std::deque、std::vector 或 std::list)实现,提供==后进先出(LIFO, Last-In-First-Out)==的数据结构行为。它不是一个独立的容器,而是通过限制底层容器的接口来实现栈的功能。
1.2 stack 的接口及使用
函数调用 | 接口说明 |
---|---|
stack() | 构造空的栈 |
empty() | 检测stack是否为空,是返回true,否则返回false |
size() | 返回stack中元素的个数 |
top() | 返回栈顶元素的引用 |
push() | 入栈 |
pop() | 将栈顶元素弹出 |
1.3 stack 的模拟实现
stack 实际上就是一种特殊的 vector,可以直接调用 vector 的接口来实现 stack。
#include <iostream>
using namespace std;#include <stack>int main()
{stack<int> st;st.push(5);st.push(4);st.push(3);st.push(2);st.push(1);while (!st.empty()){cout << "栈剩余元素:" << st.size() << " 栈顶元素为:" << st.top() << endl;st.pop();}return 0;
}
2. queue 的介绍和使用
2.1 queue 的介绍
std::queue 是 C++ 标准库中的一种容器适配器(Container Adapter),基于其他容器(如 std::deque 或 std::list)实现,提供==先进先出(FIFO, First-In-First-Out)==的数据结构行为。它不是独立的容器,而是通过封装底层容器并限制其接口来实现队列功能。
2.2 queue 的接口及使用
函数声明 | 接口说明 |
---|---|
queue() | 构造空的队列 |
empty() | 检测队列是否为空,是返回true,否则返回false |
size() | 返回队列中元素个数 |
front() | 返回队头元素的引用 |
back() | 返回队尾元素的引用 |
push() | 入队列 |
pop() | 将队头元素出队列 |
#include <iostream>
using namespace std;
#include <queue>int main()
{queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);q.push(5);while (!q.empty()){cout << "队列剩余元素个数:" << q.size() << " 队头元素:" << q.front() << " 队尾元素:" << q.back() << endl;q.pop();}return 0;
}
2.3 queue 的模拟实现
queue 需要头插和尾删,使用 vector 容器来封装的话效率太低,所以这里选择 list 容器来封装。
#include <list>
namespace zkp
{template<class T>class queue{public:queue() {}void push(const T& x) { _c.push_back(x); }void pop() { _c.pop_front(); }T& back() { return _c.back(); }const T& back()const { return _c.back(); }T& front() { return _c.front(); }const T& front()const { return _c.front(); }size_t size()const { return _c.size(); }bool empty()const { return _c.empty(); }private:std::list<T> _c;};
}
3. priority_queue的介绍和使用
3.1 priority_queue 的介绍
std::priority_queue 是 C++ 标准库中的一种容器适配器(Container Adapter),基于其他容器(如 std::vector 或 std::deque)实现,提供优先级队列的功能。它不是独立的容器,而是通过堆(Heap)数据结构自动维护元素的优先级顺序。默认情况下,元素按从大到小的顺序排列(最大堆),优先级最高的元素(即最大值)始终位于队头。
3.2 priority_queue 的接口及使用
注意:
- 默认情况下是大堆
函数声明 | 接口说明 |
---|---|
priority_queue()/priority_queue(first, last) | 构造一个空的优先级队列 |
empty() | 检测优先级队列是否为空,是返回true,否则返回false |
top() | 返回优先级队列中最大(最小元素),即堆顶元素 |
push() | 在优先级队列中插入元素 val |
pop() | 删除堆顶元素 |
#include <iostream>
using namespace std;
#include <queue>int main()
{priority_queue<int> pq;pq.push(1);pq.push(1);pq.push(4);pq.push(5);pq.push(1);pq.push(4);while (!pq.empty()){cout << "堆内元素数量为:" << pq.size() << " 堆顶元素为:" << pq.top() << endl;pq.pop();}return 0;
}
3.3 priority_queue 的模拟实现
主要还是向上调整和向下调整算法,不清楚的去看: 二叉树、堆。因为是通过传入数组来构造堆的,所以无法直接再原数组上操作,也就无法使用向下建堆法。至于迭代器版本的构造,我懒得写了,有兴趣的自己实现一下。
#include <vector>namespace zkp
{template<class T>class priority_queue{public:// 向上调整算法void AdjustUp(){int child = _c.size() - 1;int parent = (child - 1) / 2; // 通过下标关系计算出父节点下标while (child > 0) // 当子节点下标大于 0 时就继续调整{if (_c[child] < _c[parent]) // 这里以小堆为例,所以子小于父的时候交换两节点数据,将小的元素往上调{swap(_c[parent], _c[child]);child = parent;parent = (child - 1) / 2;}else{break; // 到达合适位置的时候跳出循环}}}// 向下调整算法void AdjustDown(){int parent = 0;// 假设左孩子小int child = parent * 2 + 1;while (child < _c.size()) // child >= n说明孩子不存在,调整到叶子了{// 找出小的那个孩子,确保child指向的是小的孩子节点if (child + 1 < _c.size() && _c[child + 1] < _c[child]){++child;}if (_c[child] < _c[parent]) // 孩子节点比父节点小就进行交换{swap(_c[child], _c[parent]);parent = child;child = parent * 2 + 1;}else{break; // 到合适的位置跳出循环}}}void push(T x){_c.push_back(x);AdjustUp();}void pop(){swap(_c[0], _c[_c.size() - 1]);_c.pop_back();AdjustDown();}priority_queue() {}T& top() { return _c.front(); }const T& top()const { return _c.front(); }size_t size()const { return _c.size(); }bool empty()const { return _c.empty(); }private:std::vector<T> _c;};void test(){priority_queue<int> p;p.push(1);p.push(1);p.push(4);p.push(5);p.push(1);p.push(4);while (!p.empty()){cout << "堆内元素数量为:" << p.size() << " 堆顶元素为:" << p.top() << endl;p.pop();}}
}
4. 容器适配器
4.1 什么是适配器?
总所周知,我国的家庭电路电压是 220V。我们的笔记本电脑就有一个适配器,拿我的电脑来说,它是 20V,280W的,它直接接在家用电路上肯定是不行的,所以就有了电脑适配器这玩意。它就是将家用电路的 220V电压转换成电脑能使用的 20V电压用的。
适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。
4.2 STL标准库中stack和queue的底层结构
前面就提到过,STL 中的 stack、queue 都是容器适配器,那么到底怎么体现出来呢?
4.3 deque 的简单介绍
4.3.1 deque 的原理介绍
deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。
deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:
双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示:
那deque是如何借助其迭代器维护其假想连续的结构呢?
4.3.2 deque 的缺陷
与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的。
与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。
但是,deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作为stack和queue的底层数据结构。
4.4 为什么选择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的优点,而完美的避开了其缺陷。
4.5 stack 和 queue 的模拟实现
4.5.1 stack 的模拟实现
#include<deque>
namespace zkp
{template<class T, class Con = deque<T>>//template<class T, class Con = vector<T>>//template<class T, class Con = list<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:Con _c;};
}
4.5.2 queue 的模拟实现
#include<deque>
namespace zkp
{template<class T, class Con = deque<T>>//template<class T, class Con = list<T>>class queue{public :queue() {}void push(const T& x) { _c.push_back(x); }void pop() { _c.pop_front(); }T& back() { return _c.back(); }const T& back()const { return _c.back(); }T& front() { return _c.front(); }const T& front()const { return _c.front(); }size_t size()const { return _c.size(); }bool empty()const { return _c.empty(); }private:Con _c;};
}
相关文章:

STL - stack 和 queue 及容器适配器模式的介绍
文章目录 1. stack 的介绍和使用1.1 stack 的介绍1.2 stack 的接口及使用1.3 stack 的模拟实现 2. queue 的介绍和使用2.1 queue 的介绍2.2 queue 的接口及使用2.3 queue 的模拟实现 3. priority_queue的介绍和使用3.1 priority_queue 的介绍3.2 priority_queue 的接口及使用3.…...

windows 安装gdal实现png转tif,以及栅格拼接
windows 安装gdal实现png转tif,以及栅格拼接 一、安装gdal 网上有很多安装gdal的方法,此处通过osgeo4w安装gdal 1.下载osgeo4w 下载地址 https://trac.osgeo.org/osgeo4w/ 2、安装osgeo4w exe文件安装,前面部分很简单,就不再…...
量子计算在金融科技中的应用前景
随着量子计算技术的飞速发展,其在各行业的应用潜力逐渐显现,金融科技领域更是备受关注。量子计算的强大计算能力有望为金融行业带来前所未有的变革,从风险评估到投资组合优化,从高频交易到加密技术,量子计算都可能成为…...
OpenAI Chat API 详解:打造智能对话应用的基石
目录 OpenAI Chat API 详解:打造智能对话应用的基石参数概览核心参数详解与实战1. model: 选择你的 AI 大脑2. prompt: 指引 AI 的灵魂3. max_tokens: 控制输出的长度4. temperature 和 top_p: 调控创造力5. stop: 控制生成的结束6. presence_penalty 和 frequency_…...
JavaScript性能优化实战(12):大型应用性能优化实战案例
在前面的系列文章中,我们探讨了各种JavaScript性能优化技术和策略。本篇将聚焦于实际的大型应用场景,通过真实案例展示如何综合运用这些技术,解决复杂应用中的性能挑战。 目录 电商平台首屏加载优化全流程复杂数据可视化应用性能优化案例在线协作工具的实时响应优化移动端W…...

Socket.IO是什么?适用哪些场景?
Socket.IO 详细介绍及适用场景 一、Socket.IO 是什么? Socket.IO 是一个基于事件驱动的 实时通信库,支持双向、低延迟的客户端-服务器交互。它底层结合了 WebSocket 和 HTTP 长轮询 等技术,能够在不同网络环境下自动选择最优传输方式&#x…...

深度学习入门:卷积神经网络
目录 1、整体结构2、卷积层2.1 全连接层存在的问题2.2 卷积运算2.3 填充2.4 步幅2.5 3维数据的卷积运算2.6 结合方块思考2.7 批处理 3、池化层4、卷积层和池化层的实现4.1 4维数组4.2 基于im2col的展开4.3 卷积层的实现4.4 池化层的实现 5、CNN的实现6、CNN的可视化6.1 第一层权…...

【Odoo】Pycharm导入运行Odoo15
【Odoo】Pycharm导入运行Odoo15 前置准备1. Odoo-15项目下载解压2. PsrtgreSQL数据库 项目导入运行1. 项目导入2. 设置项目内虚拟环境3. 下载项目中依赖4. 修改配置文件odoo.conf 运行Pycharm快捷运行 前置准备 1. Odoo-15项目下载解压 将下载好的项目解压到开发目录下 2. …...

pytest框架 - 第二集 allure报告
一、断言assert 二、Pytest 结合 allure-pytest 插件生成美观的 Allure 报告 (1) 安装 allure 环境 安装 allure-pytest 插件:pip install allure-pytest在 github 下载 allure 报告文件 地址:Releases allure-framework/allure2 GitHub下载&#x…...

pycharm连接github(详细步骤)
【前提:菜鸟学习的记录过程,如果有不足之处,还请各位大佬大神们指教(感谢)】 1.先安装git 没有安装git的小伙伴,看上一篇安装git的文章。 安装git,2.49.0版本-CSDN博客 打开cmd(…...
Android日活(DAU)检测的四大实现方案详解
引言 日活跃用户(DAU)是衡量应用健康度的核心指标之一。在Android开发中,实现DAU统计需要兼顾准确性、性能和隐私合规。本文将详细介绍四种主流实现方案,并提供完整的代码示例和选型建议。 方案一:本地检测方案 核心…...
2021ICPC四川省赛个人补题ABDHKLM
Dashboard - The 2021 Sichuan Provincial Collegiate Programming Contest - Codeforces 过题难度: A K D M H B L 铜奖 5 594 银奖 6 368 金奖 8 755 codeforces.com/gym/103117/problem/A 模拟出牌的过程,打表即可 // Code Start Here int t…...

oracle linux 95 升级openssh 10 和openssl 3.5 过程记录
1. 安装操作系统,注意如果可以选择,选择安装开发工具,主要是后续需要编译安装,需要gcc 编译工具。 2. 安装操作系统后,检查zlib 、zlib-dev是否安装,如果没有,可以使用安装镜像做本地源安装&a…...
httpx[http2] 和 httpx 的核心区别及使用场景如下
httpx[http2] 和 httpx 的核心区别在于 HTTP/2 协议支持,具体差异及使用场景如下: 1. 功能区别 命令/安装方式协议支持额外依赖适用场景pip install httpx仅 HTTP/1.1无通用请求,轻量依赖pip install httpx[http2]支持 HTTP/2需安装 h2>3…...
Text models —— BERT,RoBERTa, BERTweet,LLama
BERT 什么是BERT? BERT,全称Bidirectional Encoder Representations from Transformers,BERT是基于Transformer的Encoder(编码器)结构得来的,因此核心与Transformer一致,都是注意力机制。这种…...

【AGI】大模型微调数据集准备
【AGI】大模型微调数据集准备 (1)模型内置特殊字符及提示词模板(2)带有系统提示和Function calling微调数据集格式(3)带有思考过程的微调数据集结构(4)Qwen3混合推理模型构造微调数据…...

新能源汽车制动系统建模全解析——从理论到工程应用
《纯电动轻卡制动系统建模全解析:车速-阻力拟合、刹车力模型与旋转质量转换系数优化》 摘要 本文以纯电动轻卡为研究对象,系统解析制动系统建模核心参数优化方法,涵盖: 车速-阻力曲线拟合(MATLAB实现与模型验证&…...
【Linux驱动】Linux 按键驱动开发指南
Linux 按键驱动开发指南 1、按键驱动开发基础 1.1. 按键驱动类型 Linux下的按键驱动主要有两种实现方式: 输入子系统驱动:最常用,通过input子系统上报按键事件 字符设备驱动:较少用,需要自己实现文件操作接口 1.…...
湖北理元理律师事务所:债务管理的社会价值探索
债务问题从来不是孤立的经济事件,其背后牵涉家庭稳定、社会信用体系乃至区域经济发展。湖北理元理律师事务所通过五年服务数据发现:科学债务规划可使单个家庭挽回约23%的可支配收入,间接降低离婚率、心理健康问题发生率等社会成本。 债务优化…...

【Bluedroid】蓝牙HID DEVICE 报告发送与电源管理源码解析
本文基于Android蓝牙协议栈代码,深度解析HID设备(如键盘、鼠标)从应用层发送输入报告到主机设备的完整流程,涵盖数据封装、通道选择、L2CAP传输、电源管理四大核心模块。通过函数调用链(send_report → BTA_HdSendRepo…...
04、基础入门-SpringBoot官方文档架构
04、基础入门-SpringBoot官方文档架构 # Spring Boot官方文档架构 Spring Boot官方文档是学习和使用Spring Boot的重要资源,其架构清晰,内容全面,帮助用户从入门到精通。以下是官方文档的主要架构: ## 1. 引言 - **关于文档**&…...

第9章 组件及事件处理
9.1 Java Swing概述 图像用户界面(GUI) java.awt包,即Java抽象窗口工具包,Button(按钮)、TextField(文本框)、List(列表) javax.swing包 容器类(…...
三、高级攻击工具与框架
高级工具与框架是红队渗透的核心利器,能够实现自动化攻击、权限维持和隐蔽渗透。本节聚焦Metasploit、Cobalt Strike及企业级漏洞利用链,结合实战演示如何高效利用工具突破防御并控制目标。 1. Metasploit框架深度解析 定位:渗透测试的“瑞…...

用golang实现二叉搜索树(BST)
目录 一、概念、性质二、二叉搜索树的实现1. 结构2. 查找3. 插入4. 删除5. 中序遍历 中序前驱/后继结点 一、概念、性质 二叉搜索树(Binary Search Tree),简写BST,又称为二叉查找树 它满足: 空树是一颗二叉搜索树对…...
10.13 LangChain工具调用实战:@tool装饰器+小样本提示,日处理10w+调用秘籍
LangChain 工具调用(Tool Calling)深度解析 关键词:LangChain工具调用, 函数调用与工具调用区别, @tool装饰器, ToolMessage机制, 小样本提示工程 1. Function Calling vs Tool Calling LangChain 中的工具调用系统经历了从函数调用(Function Calling)到工具调用(Tool …...
C++跨平台开发经验与解决方案
在当今软件开发领域,跨平台开发已成为一个重要的需求。C作为一种强大的系统级编程语言,在跨平台开发中扮演着重要角色。本文将分享在实际项目中的跨平台开发经验和解决方案。 1. 构建系统选择 CMake的优势 跨平台兼容性好 支持多种编译器和IDE 强大…...
【以及好久没上号的闲聊】Unity记录8.1-地图-重构与优化
最近几年越来越懒,要是能分身多好哇,大家教教我 懒得更CSDN了,所以不是很常上号,而CSDN的两周前私信显示的灰灰的 也就是虽然我每次上号都有看私信,但是搞笑的是前面四个明显的消息全是CSDN的广告,我压根没…...
C# 活动窗体截图:基于 Win32 API 的实现
1. 核心功能与技术栈 该截图功能类 ScreenShotClass 基于 Win32 API 实现了两种截图方式: CopyFromScreen 方法:利用 Graphics.CopyFromScreen 直接截取屏幕区域。BitBlt 方法:通过 GDI 的位图块传输(BitBlt)实现窗口…...

服务器防文件上传手写waf
一、waf的目录结构,根据自己目录情况进行修改 二、创建文件夹以及文件 sudo mkdir -p /www/server/waf-monitor sudo mkdir -p /www/server/waf-monitor/quarantine #创建文件夹 chmod 755 /www/server/waf-monitor #赋权cd /www/server/waf-monitor/touch waf-m…...
大模型为什么学新忘旧(大模型为什么会有灾难性遗忘)?
字数:2500字 一、前言:当学霸变成“金鱼” 假设你班上有个学霸,数学考满分,英语拿第一,物理称霸全校。某天,他突然宣布:“我要全面发展!从今天起学打篮球!” 一周后&am…...