STL Stack 常见写法与深度解析
概述
stack是 C++ STL 中的容器适配器(Container Adaptor),通常基于 deque或 vector实现。它只提供了 FILO(先进后出) 的访问方式,是算法刷题和日常开发中的常用数据结构。
核心 API
| 方法 | 功能描述 | 时间复杂度 |
|---|---|---|
push() | 入栈元素 | O(1) |
pop() | 弹出栈顶(无返回值) | O(1) |
top() | 访问栈顶元素(返回引用) | O(1) |
empty() | 检查是否为空 | O(1) |
size() | 获取元素个数 | O(1) |
1. 基础语法与定义
基本定义
#include <stack>
#include <vector>
#include <string>
using namespace std;
// 定义一个存放 int 类型元素的栈(默认基于 deque)
stack<int> s;
// 定义一个存放 string 类型元素的栈
stack<string> s2;
// 使用 vector 作为底层容器
stack<int, vector<int>> myVecStack;
注意事项
- stack 本身不支持遍历或随机访问,仅能访问栈顶元素
top() - pop() 没有返回值,仅删除栈顶元素
- 必须先检查 empty() 再调用 top() ,否则会导致未定义行为
2. 常见写法与处理手段
基础操作:压栈与弹栈
stack<int> mystack;
// 压栈操作
mystack.push(1);
mystack.push(2);
mystack.push(3); // 栈顶现在是 3
// 弹出操作
mystack.pop(); // 弹出 3
// 访问栈顶
if(!mystack.empty()){
cout << mystack.top(); // 输出 2
}
安全获取并弹出元素
// 错误写法:pop() 没有返回值
// int val = mystack.pop();
// 正确写法:先获取再弹出
if(!mystack.empty()){
int val = mystack.top();
mystack.pop();
// 使用 val...
}
遍历栈(需要临时栈)
// 如果需要遍历栈,需要创建临时栈
stack<int> temp = mystack;
while(!temp.empty()){
cout << temp.top() << " ";
temp.pop();
}
5. 进阶技巧与注意事项
技巧1:使用 pair 存储额外信息
// 在单调栈中存储值和索引
stack<pair<int, int>> st; // first: 值, second: 索引
// 在计算器问题中存储操作数和运算符
stack<int> nums;
stack<char> ops;
技巧2:空栈检查的重要性
// 危险写法
// cout << mystack.top(); // 如果栈空,UB
// 安全写法
if(!mystack.empty()){
cout << mystack.top();
}
技巧3:栈的清空
// 方法1:循环弹出
while(!mystack.empty()){
mystack.pop();
}
// 方法2:交换空栈(C++11+)
stack<int> empty;
swap(mystack, empty);
6. 常见错误与调试
错误1:忘记检查空栈
stack<int> s;
// s.pop(); // 未定义行为
// s.top(); // 未定义行为
if(!s.empty()){
s.pop(); // 安全
}
错误2:误解 pop() 行为
stack<int> s;
s.push(1);
s.push(2);
// 错误:以为 pop() 返回元素
// int val = s.pop();
// 正确
int val = s.top();
s.pop();
错误3:遍历时修改栈
// 错误:遍历时修改栈大小
for(int i=0; i<s.size(); i++){
s.pop(); // 大小在变化,循环次数错误
}
// 正确
while(!s.empty()){
s.pop();
}