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

从 C 到 C++:容器适配器 std::stack 与 std::queue 详解

        对于刚从 C 语言转向 C++ 的朋友来说,标准库中的容器适配器是提升开发效率的利器。std::stack(栈)和std::queue(队列)作为两种常用的容器适配器,封装了底层容器的复杂细节,提供了简洁直观的操作接口,彻底告别了 C 语言中手动实现栈和队列的繁琐。本文将详细介绍这两种适配器的特性、底层实现及完整操作指南。

一、什么是容器适配器?

        容器适配器(Container Adapters)是 C++ 标准库提供的一种特殊容器,它不直接存储数据,而是通过封装(适配)其他基础容器(如vectordeque)来提供特定的数据操作接口。

  • 适配器的本质是接口转换:将基础容器的通用接口转换为满足特定数据结构需求的专用接口
  • 优势:无需关心底层实现细节,专注于业务逻辑,代码更简洁、更不易出错

二、栈(std::stack)详解

   std::stack实现了后进先出(LIFO, Last In First Out) 的数据结构,只能从容器的一端(称为 "栈顶")插入和删除元素。

2.1 底层默认容器

   std::stack的默认底层容器是std::deque(双端队列),这是因为deque同时满足栈对尾部插入 / 删除高效性(O (1) 时间复杂度)和动态扩容的需求。当然,也可以手动指定其他底层容器(需支持push_back()pop_back()back()empty()size()等操作),如std::vectorstd::list

// 以vector为底层容器的栈
std::stack<int, std::vector<int>> stack_with_vector;// 以list为底层容器的栈
std::stack<int, std::list<int>> stack_with_list;

2.2 头文件与初始化

#include <stack>  // 必须包含的头文件
#include <deque>  // 底层默认容器,通常无需显式包含
using namespace std;// 初始化方式
stack<int> st1;  // 空栈(默认使用deque作为底层容器)// 从其他容器初始化(需通过中间容器转换)
deque<int> dq = {1, 2, 3};
stack<int> st2(dq);  // 栈顶元素为3(因为栈会按dq的元素顺序堆叠)

2.3 核心操作表

操作函数接口代码示例(基于 st2 = {1,2,3},栈顶为 3)功能说明时间复杂度
入栈push(value)st2.push(4); → 栈变为 {1,2,3,4}在栈顶插入元素O(1)
出栈pop()st2.pop(); → 栈变为 {1,2}移除栈顶元素(不返回值)O(1)
访问栈顶元素top()cout << st2.top(); → 输出 3返回栈顶元素的引用O(1)
判断是否为空empty()if(st2.empty()) → false栈为空返回 true,否则返回 falseO(1)
获取元素个数size()cout << st2.size(); → 3返回栈中元素的数量O(1)

2.4 基本操作使用示例

#include <stack>
#include <iostream>
using namespace std;int main() {stack<int> st;// 入栈操作st.push(10);st.push(20);st.push(30);cout << "栈大小:" << st.size() << endl;  // 输出:3cout << "栈顶元素:" << st.top() << endl;  // 输出:30// 出栈操作st.pop();cout << "出栈后栈顶元素:" << st.top() << endl;  // 输出:20// 遍历栈(需注意:栈没有迭代器,必须通过出栈操作遍历)cout << "栈中所有元素(从栈顶到栈底):";while (!st.empty()) {cout << st.top() << " ";  // 依次输出20、10st.pop();}// 遍历后栈为空cout << "\n遍历后栈是否为空:" << (st.empty() ? "是" : "否") << endl;  // 输出:是return 0;
}

三、队列(std::queue)详解

   std::queue实现了先进先出(FIFO, First In First Out) 的数据结构,元素从一端(队尾)插入,从另一端(队首)删除。

3.1 底层默认容器

   std::queue的默认底层容器也是std::deque(双端队列),选择deque的原因是它能同时高效支持队尾插入队首删除操作(均为 O (1) 时间复杂度),这是vector无法比拟的(vector的队首删除需要移动所有元素,O (n) 复杂度)。同样可以指定其他底层容器(需支持push_back()pop_front()front()back()empty()size()等操作),如std::list

// 以list为底层容器的队列
std::queue<int, std::list<int>> queue_with_list;

3.2 头文件与初始化

#include <queue>  // 必须包含的头文件
using namespace std;// 初始化方式
queue<int> q1;  // 空队列(默认使用deque作为底层容器)// 从其他容器初始化
deque<int> dq = {10, 20, 30};
queue<int> q2(dq);  // 队列:队首10,队尾30

3.3 核心操作表

操作函数接口代码示例(基于 q2 = {10,20,30},队首 10,队尾 30)功能说明时间复杂度
入队push(value)q2.push(40); → 队列变为 {10,20,30,40}在队尾插入元素O(1)
出队pop()q2.pop(); → 队列变为 {20,30}移除队首元素(不返回值)O(1)
访问队首元素front()cout << q2.front(); → 输出 10返回队首元素的引用O(1)
访问队尾元素back()cout << q2.back(); → 输出 30返回队尾元素的引用O(1)
判断是否为空empty()if(q2.empty()) → false队列为空返回 true,否则返回 falseO(1)
获取元素个数size()cout << q2.size(); → 3返回队列中元素的数量O(1)

3.4 基本操作使用示例

#include <queue>
#include <iostream>
using namespace std;int main() {queue<int> q;// 入队操作q.push(100);q.push(200);q.push(300);cout << "队列大小:" << q.size() << endl;  // 输出:3cout << "队首元素:" << q.front() << endl;  // 输出:100cout << "队尾元素:" << q.back() << endl;   // 输出:300// 出队操作q.pop();cout << "出队后队首元素:" << q.front() << endl;  // 输出:200// 遍历队列(需注意:队列没有迭代器,必须通过出队操作遍历)cout << "队列中所有元素(从队首到队尾):";while (!q.empty()) {cout << q.front() << " ";  // 依次输出200、300q.pop();}// 遍历后队列为空cout << "\n遍历后队列是否为空:" << (q.empty() ? "是" : "否") << endl;  // 输出:是return 0;
}

四、C 语言实现 vs C++ 容器适配器对比

特性C 语言手动实现栈 / 队列C++ std::stack/std::queue
实现复杂度需要手动定义结构体(节点 / 数组)、处理指针 / 索引无需实现底层逻辑,直接调用接口即可
内存管理需手动 malloc/free,易发生内存泄漏或越界自动管理内存,析构函数自动释放资源
接口一致性不同实现者的函数命名和参数差异大标准接口,所有环境下用法一致,降低学习成本
扩展性如需修改底层实现(数组改链表),需重写所有函数仅需修改模板参数即可更换底层容器,上层代码无需变动
安全性无边界检查,容易访问越界操作更安全,如对空栈调用 top () 虽未定义,但实践中风险更低

五、使用场景指南

std::stack 适用场景

  • 表达式求值(如后缀表达式计算)
  • 函数调用栈模拟
  • 括号匹配检查
  • 深度优先搜索(DFS)的递归替代实现
  • 撤销操作(如文本编辑器的撤销功能)

std::queue 适用场景

  • 任务调度系统(如打印队列)
  • 广度优先搜索(BFS)
  • 生产者 - 消费者模型
  • 缓存机制实现
  • 消息队列系统

六、注意事项

无迭代器

  stackqueue都不提供迭代器,无法像vectorlist那样遍历容器中所有元素(除非通过出栈 / 出队操作),这是为了保证其数据操作的规范性(严格遵循 LIFO/FIFO)。

底层容器选择

  stack默认使用deque,也可选择vector(尾部操作高效)或list(内存分配更灵活)queue推荐使用默认的dequelist,不建议使用vector(队首删除效率低)

异常处理

      对空栈调用top()pop(),对空队列调用front()back()pop()都是未定义行为,实际使用中需先通过empty()检查容器状态。

七、总结

  std::stackstd::queue作为 C++ 标准库的容器适配器,为开发者提供了简洁、高效、安全的栈和队列实现:

  • 无需关心底层数据结构细节,专注于业务逻辑
  • 统一的接口设计降低了学习和使用成本
  • 自动内存管理避免了 C 语言中常见的内存问题

      对于从 C 转向 C++ 的朋友来说,熟练掌握这些容器适配器能显著提高代码质量和开发效率,是迈向 C++ 标准库熟练使用者的重要一步。在 C++ 中,善用标准库是非常重要的!

http://www.dtcms.com/a/483196.html

相关文章:

  • 工信部网站备案查询 验证码错误2019年建设银行安徽招聘网站
  • wordpress网站如何搬家wordpress开发入门视频教程
  • 电子商务网站建设与管理思考与练习做暧视频免费网站
  • 建站公司兴田德润网页制作模板 html
  • Spring Boot 3零基础教程,深度理解 Spring Boot 自动配置原理,笔记11
  • PHP MQTT 订阅服务:实时消息接收与数据库存储解决方案
  • 设计网站网站名称冒用公司名做网站
  • Android进阶之路 - 全方位监听视图加载完成
  • PPT-EA:PPT自动生成器
  • 企业微信-智能表格-视图类型
  • 产品网站建设PHP MYSQL网站开发全程实
  • 性能优化-Vue3 + Vite:图片上传/优化到 OSS 并统一使用vite 的 .env 全局配置,js 和 css 共用变量
  • 网站建设项目背景杭州一起做网站
  • 做最好的色书网站半透明wordpress主题源码
  • 17.UE-游戏逆向-查找Aactor(游戏中物品的名字和坐标)
  • 扫黄打非网站建设wordpress上传视频插件
  • 手机网站底部广告代码wordpress版本下载
  • 量子计算与深度学习:新时代材料模拟实战
  • SMTPman,smtp服务器高效邮件发送核心指南
  • UE C++ TMap容器的 创建和遍历
  • 域名与网站名称的关系企业发展历程网站
  • MyBatis-Flex 来了
  • 带权并查集
  • 建设网站多少钱 郑州浏览器什么网站都能打开的
  • 安卓13_ROM修改定制化-----常用几种去除系统签名类验证的操作步骤解析
  • 安卓导出谷歌包
  • 上海百度网络推广极限优化wordpress
  • 南京市建设监理协会网站dedecms 网站根目录
  • 创建Mybatis框架
  • 从化网站建设方案百度网站好评