后进先出(LIFO)的容器适配器——只能在栈顶操作,像一摞盘子,只能从最上面放、从最上面取。
stack 是一种后进先出(LIFO,Last In First Out)的容器适配器。它底层默认使用 deque 实现,只开放有限的接口,只允许在栈顶进行插入和删除操作。形象地理解,它就像一摞盘子——你只能放新的在最上面,也只能从最上面取走。使用前需引入 <stack> 头文件。
stack 是容器适配器,不是独立容器,它底层默认用 deque 实现,只开放有限的接口。不能用迭代器遍历它。top() 或 pop() 是未定义行为,使用前务必用 empty() 检查。
| 1 | #include <iostream> |
| 2 | #include <stack> // 必须包含这个头文件 |
| 3 | using namespace std; |
| 4 | |
| 5 | int main() |
| 6 | { |
| 7 | stack<int> s1; // 空栈 |
| 8 | stack<int> s2(s1); // 拷贝另一个栈 |
| 9 | return 0; |
| 10 | } |
| 1 | stack<int> s; |
| 2 | // 压入元素 |
| 3 | s.push(1); // 栈:[1] |
| 4 | s.push(2); // 栈:[1, 2] |
| 5 | s.push(3); // 栈:[1, 2, 3] |
| 6 | |
| 7 | // 查看栈顶 |
| 8 | cout << s.top() << endl; // 输出:3(栈顶元素) |
| 9 | |
| 10 | // 弹出栈顶 |
| 11 | s.pop(); // 弹出 3,栈变成 [1, 2] |
| 12 | |
| 13 | // 容量 |
| 14 | cout << s.size() << endl; // 输出:2 |
| 15 | cout << s.empty() << endl; // 输出:0(false,不空) |
| 16 | |
| 17 | // 交换 |
| 18 | s1.swap(s2); // 交换两个栈的全部内容 |
| 19 | s.emplace(10); // 在栈顶原地构造元素(比 push 更高效) |
陷阱一:pop() 不返回被删除的值!
| 1 | stack<int> s; |
| 2 | s.push(10); |
| 3 | |
| 4 | // ❌ 错误写法——pop() 返回 void,不能赋值 |
| 5 | int x = s.pop(); // 编译错误! |
| 6 | |
| 7 | // ✅ 正确写法——先取栈顶,再弹出 |
| 8 | int x = s.top(); // 先拿到 10 |
| 9 | s.pop(); // 再把 10 弹出 |
pop() 的设计哲学是"删除"和"读取"分开:pop() 只负责删除,返回类型是 void;要读取栈顶的值,必须先调用 top()。这和很多人直觉里"弹出并返回"的想法不一样,是 STL 容器适配器里最容易踩的坑之一。陷阱二:空栈调用 top() 或 pop() 是危险操作
| 1 | stack<int> s; // 空栈 |
| 2 | |
| 3 | // ❌ 危险!程序可能直接崩溃 |
| 4 | cout << s.top(); |
| 5 | s.pop(); |
| 6 | |
| 7 | // ✅ 安全做法——操作前先检查 |
| 8 | if (!s.empty()) |
| 9 | { |
| 10 | cout << s.top(); |
| 11 | s.pop(); |
| 12 | } |
| 1 | #include <iostream> |
| 2 | #include <stack> |
| 3 | using namespace std; |
| 4 | |
| 5 | int main() |
| 6 | { |
| 7 | stack<int> s; |
| 8 | |
| 9 | // 压入三个元素 |
| 10 | s.push(1); |
| 11 | s.push(2); |
| 12 | s.push(3); |
| 13 | |
| 14 | cout << "栈顶: " << s.top() << endl; // 输出:3 |
| 15 | cout << "大小: " << s.size() << endl; // 输出:3 |
| 16 | |
| 17 | // 逐个弹出(后进先出) |
| 18 | cout << "依次弹出: "; |
| 19 | while (!s.empty()) |
| 20 | { |
| 21 | cout << s.top() << " "; // 输出:3 2 1 |
| 22 | s.pop(); |
| 23 | } |
| 24 | cout << endl; |
| 25 | |
| 26 | cout << "是否为空: " << s.empty() << endl; // 输出:1(true) |
| 27 | |
| 28 | return 0; |
| 29 | } |
把本节出现过的方法按用途归类汇总,写代码时可以直接当参考卡用。
| 方法 | 分类 | 作用 |
|---|---|---|
| s.push(x) | 修改 | 压入元素到栈顶 |
| s.pop() | 修改 | 弹出栈顶元素,不返回值 |
| s.emplace(args...) | 修改 | 在栈顶原地构造元素,省去拷贝 |
| s.top() | 访问 | 读取(不删除)栈顶元素 |
| s.size() / s.empty() | 容量 | 元素个数 / 判断是否为空 |
| s1.swap(s2) | 修改 | 交换两个栈的全部内容 |
stack 的舞台。