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

43 C++ STL模板库12-容器4-容器适配器-堆栈(stack)

C++ STL模板库12-容器4-容器适配器-堆栈(stack)

文章目录

  • C++ STL模板库12-容器4-容器适配器-堆栈(stack)
    • 一、模板参数与底层容器
      • 头文件与命名空间
      • 模板声明
    • 二、成员函数列表
    • 三、非成员函数
    • 四、特性与注意事项
    • 五、示例代码片段
      • 示例1:基本操作(`push`/`top`/`pop`/`empty`/`size`)
      • 示例2:高效构造(`emplace`代替`push`)
      • 示例3:更换底层容器(`vector`/`list`)
      • 示例4:交换两个栈(`swap`)
      • 示例5:安全访问与错误处理
      • 示例6:比较两个栈(运算符重载)
      • 示例7:作为函数的参数类型传递

stack是一个容器适配器,它基于其他容器实现.

一、模板参数与底层容器

头文件与命名空间

#include <stack>
using namespace std; // 或显式使用 std::stack 

模板声明

template <class T, class Container = deque<T>> class stack;

T:元素类型。
Container:底层容器类型(需满足以下操作):
back():访问末尾元素。
push_back():在末尾添加元素。
pop_back():移除末尾元素。
支持的容器:deque(默认)、vectorlist
示例stack<int, vector<int>> s; 使用 vector 作为底层容器。

二、成员函数列表

  1. push(const T& value)
    将元素压入栈顶,通过复制或移动构造(时间复杂度:O(1))。
  2. emplace(Args&&... args) (C++11)
    直接在栈顶构造元素,参数传递给元素的构造函数(更高效,避免临时对象)。
  3. pop()
    移除栈顶元素(必须先检查栈非空,否则未定义行为;时间复杂度:O(1))。
  4. top()
    返回栈顶元素的引用(允许修改值,如 s.top() = 10;,需保证栈非空)。
  5. empty()
    返回布尔值,判断栈是否为空(时间复杂度:O(1))。
  6. size()
    返回当前栈中元素的数量(时间复杂度:O(1))。
  7. swap(stack& other) (C++11)
    交换两个栈的内容(要求底层容器类型相同;时间复杂度:O(1))。

三、非成员函数

  1. swap(stack& a, stack& b) (C++11)
    交换两个栈的内容(等效于 a.swap(b))。

  2. 比较运算符 (==, !=, <, <=, >, >=)
    按字典序比较两个栈的内容(委托到底层容器的比较操作,要求容器类型相同)。

四、特性与注意事项

  1. LIFO原则:后进先出,仅允许操作栈顶元素。
  2. 无迭代器:不支持遍历,只能通过 top() 访问栈顶。
  3. 性能依赖底层容器:
    • 默认使用 deque,平衡内存分配效率。
    • 使用 vector 时需注意扩容开销。
  4. 错误处理:
    • pop()top() 前必须用 empty() 检查栈非空。
    • 未定义行为风险:如空栈调用 pop()

五、示例代码片段

示例1:基本操作(push/top/pop/empty/size

#include <stack>
#include <vector>int main() {std::stack<int, std::vector<int>> s;s.push(1);          // 栈顶元素为 1 s.emplace(2);       // 栈顶元素为 2 s.top() = 3;        // 修改栈顶为 3 s.pop();            // 移除 3,栈顶变为 1 return 0;
}

示例2:高效构造(emplace代替push

#include <stack>
#include <string>int main() {std::stack<std::string> s;s.push("abc");              // 通过临时对象构造 s.emplace(3, 'x');          // 直接构造字符串"xxx"(避免复制)return 0;
}

示例3:更换底层容器(vector/list

#include <stack>
#include <vector>
#include <list>int main() {// 使用 vector 作为底层容器(需包含头文件 <vector>)std::stack<int, std::vector<int>> s_vec;s_vec.push(5);  // 实际调用 vector::push_back()// 使用 list 作为底层容器(需包含头文件 <list>)std::stack<double, std::list<double>> s_list;s_list.push(3.14);  // 实际调用 list::push_back()return 0;
}

示例4:交换两个栈(swap

#include <stack>int main() {std::stack<int> s1, s2;s1.push(100); s2.push(200);s1.swap(s2);        // 成员函数交换 // swap(s1, s2);    // 非成员函数等效操作(C++11起)// 此时 s1.top() = 200,s2.top() = 100 return 0;
}

示例5:安全访问与错误处理

#include <stack>void processStack(std::stack<int>& s) {if (!s.empty()) {   // 必须检查非空!int val = s.top();s.pop();// 处理val...}
}int main() {std::stack<int> s;processStack(s);    // 安全处理空栈 return 0;
}

示例6:比较两个栈(运算符重载)

#include <stack>int main() {std::stack<int> a, b;a.push(1); a.push(2);  // a: [1,2]b.push(1); b.push(3);  // b: [1,3]bool isEqual = (a == b);   // false(元素不同)bool isLess = (a < b);     // true(2 < 3)return 0;
}

示例7:作为函数的参数类型传递

#include <iostream>
#include <stack>
#include <vector>
#include <list>
#include <string>template <typename T, typename Container>
void print(std::stack<T, Container> s) {std::cout << "TOP → ";while (!s.empty())  {if constexpr (std::is_same_v<T, std::string>) std::cout << "\"" << s.top()  << "\"";else std::cout << s.top(); s.pop(); if (!s.empty())  std::cout << " → ";}std::cout << " ← BOTTOM\n";
}int main() {// 使用 vector 作为底层容器(需包含头文件 <vector>)std::stack<int, std::vector<int>> s_vec;s_vec.push(5);  // 实际调用 vector::push_back()// 使用 list 作为底层容器(需包含头文件 <list>)std::stack<double, std::list<double>> s_list;s_list.push(3.14);  // 实际调用 list::push_back()print(s_vec);    //TOP → 5 ← BOTTOMprint(s_list);   //TOP → 3.14 ← BOTTOMstd::stack<std::string> s;s.push("天津");s.push("上海");// s.emplace(3, "深圳");  //错误! 底层没有匹配的函数s.emplace(std::string(" 深圳"));  // 等效于 push s.emplace(" 深圳");    // 直接构造字符串print(s);      // TOP → " 深圳" → " 深圳" → "上海" → "天津" ← BOTTOMreturn 0;
}
http://www.dtcms.com/a/336279.html

相关文章:

  • 百度笔试编程题 选数
  • PWM控制LED亮度:用户态驱动开发详解
  • Soundraw - 你的AI音乐生成器
  • 51单片机-驱动静态数码管和动态数码管模块
  • linux线程被中断打断,不会计入调度次数
  • 解决 SECURE_PCI_CONFIG_SPACE_ACCESS_VIOLATION蓝屏报错
  • 攻防世界—unseping(反序列化)
  • 机器学习----PCA降维
  • RocketMQ面试题-未完
  • 芋道RBAC实现介绍
  • python+flask后端开发~项目实战 | 博客问答项目--模块化文件架构的基础搭建
  • Valgrind 并发调试 ·:用 Helgrind 抓住线程里的“看不见的错”
  • 数据结构:在二叉搜索树中插入元素(Insert in a BST)
  • linux-高级IO(上)
  • 猫头虎AI分享|一款Coze、Dify类开源AI应用超级智能体Agent快速构建工具:FastbuildAI
  • #买硬盘欲安装k8s记
  • Flutter 3.35 更新要点解析
  • ICCV 2025 | Reverse Convolution and Its Applications to Image Restoration
  • 如何运用好DeepSeek为自己服务:智能增强的范式革命 1.2 DeepSeek认知增强模型
  • 计算机基础速通--数据结构·图的基础应用三(基础图算法进阶)
  • Tauri 框架介绍
  • 《Nursing Research》(护理SCI)LaTeX模板详细教程:从入门到投稿(一)
  • 炒股术语:“洗盘”
  • LLM入门学习
  • 【165页PPT】锂电池行业SAP解决方案(附下载方式)
  • 【C++】Windows 下 TCP接口超详介绍,如何实现一个TCP服务端和客户端
  • 又一家茑屋书店即将歇业,精品书店的未来在哪里?
  • ruoyi-vue(十一)——代码生成
  • Python爬虫实战:研究optimesh库,构建Github网格数据采集系统
  • AntSK-PyAPI技术深度解析:打造企业级文本嵌入向量服务的完整指南