栈结构的总结
竞赛/基础
栈是什么?
栈(Stack) 是一种 先进后出(FILO) 的线性数据结构,类似于叠盘子:最后放上去的盘子会被最先取走。
核心特性:只能在一端(栈顶)进行插入(入栈)和删除(出栈)操作
- 基本操作:
push():元素入栈,放到栈顶。pop():栈顶元素出栈。peek():查看栈顶元素(不删除)。isEmpty():判断栈是否为空。- 时间复杂度:所有操作均为 O(1) [[1,3]]。
栈就像一摞叠在一起的盘子️,有两大特点:
- 后进先出:最后放上去的盘子,总是第一个被拿走
- 只能操作顶部:拿/放盘子只能从最上面操作
栈的四大应用
| 应用场景 | 生活比喻 | 小例子 |
|---|---|---|
| 撤销功能 | 写错字时的橡皮擦 | 按 Ctrl+Z 撤销操作 |
| 浏览器后退 | 参观博物馆的返程路线 | 点击←返回上一网页 |
| 括号匹配 | 乐高积木的拼插顺序 | (({[]})) 是否合法 |
| 迷宫路径 | 面包屑寻路法 | 用栈记录走过的路线 |
数组实现栈(手撕栈结构)
#include <iostream>
using namespace std;
int stack[100]; // 栈数组,最大容量为100
int top = -1; // 栈顶指针,初始化为-1表示栈为空
// 压栈操作
void push(int x) {
if (top >= 99) {
cout << "⚠️ 栈满啦!不能再放啦~" << endl;
return;
}
stack[++top] = x; // 先上移栈顶指针,再放入元素
}
// 弹栈操作
int pop() {
if (top < 0) {
cout << "⚠️ 栈空啦!没有东西能拿~" << endl;
return 0;
}
return stack[top--]; // 先取出元素,再下移栈顶指针
}
// 查看栈顶元素
int peek() {
if (top < 0) {
cout << "⚠️ 栈空啦!没有东西能看~" << endl;
return 0;
}
return stack[top];
}
int main() {
push(10); // 放入10
push(20); // 放入20
push(30); // 放入30
cout << "栈顶元素: " << peek() << endl; // 查看栈顶元素,输出30
cout << "弹出元素: " << pop() << endl; // 弹出30
cout << "弹出元素: " << pop() << endl; // 弹出20
cout << "栈是否为空: " << (top < 0) << endl; // 判断栈是否为空,输出0(false)
push(40); // 放入40
push(50); // 放入50
push(60); // 放入60,如果栈已满,输出警告信息
return 0;
}
- 空栈条件:
top == -1[[12]]。 - 满栈条件:
top == capacity - 1[[12, 19]]
操作演示
栈顶元素: 30
弹出元素: 30
弹出元素: 20
栈是否为空: 0
注意事项
- 栈溢出:数组大小固定,需提前预判容量,避免
push时栈满 [[10, 12]]。 - 空栈处理:
pop或peek前检查isEmpty(),防止越界错误 [[19]]。 - 应用选择:根据问题特性选择数组或链表实现,例如需要动态扩容时用链栈 [[6, 15]]。
C++系统自带的栈使用
-
包含头文件:
要使用栈,首先需要包含stack头文件。#include <stack> -
创建栈对象:
你可以创建一个栈对象,指定存储元素的类型。如果不指定,则默认为int类型。std::stack<int> mystack; -
基本操作:
push():向栈中添加元素。pop():移除栈顶元素。top():获取栈顶元素的引用,不移除它。empty():检查栈是否为空。size():返回栈中元素的数量。
// 向栈中添加元素 mystack.push(10); mystack.push(20); mystack.push(30); // 获取栈顶元素 int topElement = mystack.top(); // topElement 现在是 30 // 移除栈顶元素 mystack.pop(); // 再次获取栈顶元素 topElement = mystack.top(); // topElement 现在是 20 // 检查栈是否为空 bool isEmpty = mystack.empty(); // isEmpty 是 false // 获取栈的大小 size_t stackSize = mystack.size(); // stackSize 是 2 -
示例代码:
下面是一个使用 C++ STLstack的完整示例代码。#include <iostream> #include <stack> using namespace std; int main() { stack<int> mystack; // 向栈中添加元素 mystack.push(10); mystack.push(20); mystack.push(30); // 输出栈顶元素并移除 while (!mystack.empty()) { cout << "弹出元素: " << mystack.top() << endl; mystack.pop(); } // 检查栈是否为空 cout << "栈是否为空: " << (mystack.empty() ? 1 : 0) << endl; return 0; }
这段代码使用了 C++ 的 `stack` 容器来演示栈的基本操作。下面是代码的详细解释:
1. 包含头文件 `<iostream>` 和 `<stack>`,分别用于输入输出和栈容器。
2. 在 `main()` 函数中定义一个 `stack` 对象 `mystack`,用于存储整数类型的元素。
3. 使用 `push()` 方法向栈中添加三个元素:10、20 和 30。
4. 使用 `while` 循环检查栈是否为空,不为空则输出栈顶元素并移除,直到栈为空。
5. 最后检查栈是否为空,输出结果(非空为1,空为0)。
运行这段代码,输出结果为:
弹出元素: 30
弹出元素: 20
弹出元素: 10
栈是否为空: 1
# 经典例题
### 希蒙的羽毛球筒
https://ac.xiaosaima.com/d/CD01_2404/p/470
```c
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> balls(n);
for (int i = 0; i < n; ++i) {
cin >> balls[i];
}
stack<int> s; // 使用 stack 模拟球筒
vector<int> result; // 存储取球的顺序
for (int ball : balls) {
if (s.empty() || ball <= s.top()) {
s.push(ball); // 可以放入球筒
}
}
// 输出取球序列
while (!s.empty()) {
result.push_back(s.top());
s.pop();
}
// 输出结果
for (int i = result.size() - 1; i >= 0; --i) {
if (i == 0) {
cout << result[i];
} else {
cout << result[i] << " ";
}
}
return 0;
}
括弧匹配检验(栈)
https://ac.xiaosaima.com/d/CD01_2404/p/459
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int main() {
string s;
cin >> s;
stack<char> st;
for (char c : s) {
if (c == '(' || c == '[') {
st.push(c); // 左括号入栈
} else if (c == ')' || c == ']') {
if (st.empty()) {
cout << "Wrong" << endl;
return 0;
}
char top = st.top();
st.pop();
if ((c == ')' && top != '(') || (c == ']' && top != '[')) {
cout << "Wrong" << endl;
return 0;
}
}
}
if (st.empty()) {
cout << "OK" << endl;
} else {
cout << "Wrong" << endl;
}
return 0;
}

浙公网安备 33010602011771号