STL:Stack详解
说到 C++ 的 STL(Standard Template Library)容器,vector
、map
、set
这些可能更常被使用。但在某些特定的应用场景下,stack
(栈)却能带来意想不到的简洁和高效。
一、stack
是啥?
stack
,中文叫"栈",是 后进先出(LIFO) 的线性数据结构。 也就是说:你最后压进去的元素,会第一个被弹出来。
举个现实中的例子: 你往一个盒子里一个一个地放盘子(push),最后放进去的盘子在最上面,如果现在要拿一个盘子出来,你只能从最上面开始拿(pop)。
在 C++ 中,stack
就是对这种行为的一种封装。
(其实这些大家在学数据结构的时候应该都有所了解了)
二、stack 的基本用法
cpp
#include <iostream>
#include <stack>
int main() {
std::stack<int> s;
s.push(10); // 压入10
s.push(20); // 压入20
s.push(30); // 压入30
std::cout << "栈顶元素:" << s.top() << std::endl; // 输出30
s.pop(); // 弹出30
std::cout << "现在栈顶是:" << s.top() << std::endl; // 输出20
return 0;
}
stack
的常用操作
操作名 | 含义 | 说明 |
---|---|---|
push() |
入栈 | 把元素放入栈顶 |
pop() |
出栈 | 弹出栈顶元素(不返回) |
top() |
查看栈顶 | 返回栈顶元素 |
empty() |
是否为空 | 栈为空返回 true |
size() |
元素数量 | 返回当前栈中元素的数量 |
三、stack 本质上是个"适配器"
stack
是一个容器,其实它的底层是对其他容器的"包装"。 它不是一个容器类,而是一个容器适配器(container adapter)。
什么意思?
在源码中,stack
默认是用 deque
作为底层容器来实现的。你也可以换成 vector
等,只要它支持:
push_back()
pop_back()
back()
cpp
std::stack<int, std::vector<int>> myStack; // 用 vector 作为底层容器
所以说,stack
只是把底层容器的接口"裁剪"了一下,只保留了能实现"栈"操作的那一部分。
适配器这个东西也很有讲头,如果大家喜欢的话,我后续会出一期~
四、常见应用场景
很多经典算法,背后都有 stack
的影子:
- 括号匹配:判断表达式是否配对,经典栈应用。
- 中缀转后缀表达式:用来临时保存运算符。
- 深度优先搜索(DFS):显式栈代替递归。
- 浏览器的前进后退:前进栈 + 后退栈。
cpp
// 一个简单的括号匹配
bool isValidBrackets(const std::string& s) {
std::stack<char> st;
for (char c : s) {
if (c == '(') st.push(c);
else if (c == ')') {
if (st.empty()) return false;
st.pop();
}
}
return st.empty();
}
五、栈的性能与注意事项
stack
的每次操作都是 常数时间 O(1),性能非常好。- 不支持迭代器遍历(你不能用 for 去遍历它),这也是刻意设计的,因为栈的原则就是 只能看最上面的那个元素。
- 如果你需要频繁地遍历或随机访问,
stack
可能不是最佳选择,考虑用vector
或deque
。
六、总结一下
- C++ 的
stack
是 STL 提供的容器适配器,封装了"后进先出"的数据结构; - 默认使用
deque
作为底层容器; - 提供简单高效的
push/pop/top/empty/size
接口; - 是括号匹配、DFS、表达式求值等算法的利器;
- 若有遍历需求,需另选容器。
简单的一篇STL容器讲解,大家的支持就是我更新的动力~