void pop() {
if (top < 0) {
cout << "Stack Underflow" << endl;
return;
}
top--;
}
Pop操作示意图:

注意事项:
Top操作:
int top() {
if (top < 0) {
cout << "Stack is Empty" << endl;
return -1;
}
return arr[top];
}
注意事项:
bool isEmpty() {
return (top < 0);
}
int size() {
return top + 1;
}
bool isFull() {
return (top == capacity - 1);
}
void clear() {
top = -1;
}
完整实现代码:
class ArrayStack {
private:
int* arr;
int top;
int capacity;
public:
ArrayStack(int size) {
arr = new int[size];
capacity = size;
top = -1;
}
~ArrayStack() {
delete[] arr;
}
void push(int x) {
if (isFull()) {
cout << "Stack Overflow" << endl;
return;
}
arr[++top] = x;
}
int pop() {
if (isEmpty()) {
cout << "Stack Underflow" << endl;
return -1;
}
return arr[top--];
}
int peek() {
if (isEmpty()) return -1;
return arr[top];
}
bool isEmpty() { return top == -1; }
bool isFull() { return top == capacity - 1; }
int size() { return top + 1; }
};
完整实现代码:
class LinkedListStack {
private:
struct Node {
int data;
Node* next;
Node(int d) : data(d), next(nullptr) {}
};
Node* top;
int stackSize;
public:
LinkedListStack() : top(nullptr), stackSize(0) {}
~LinkedListStack() {
while (!isEmpty()) {
pop();
}
}
void push(int x) {
Node* newNode = new Node(x);
newNode->next = top;
top = newNode;
stackSize++;
}
int pop() {
if (isEmpty()) {
cout << "Stack Underflow" << endl;
return -1;
}
int value = top->data;
Node* temp = top;
top = top->next;
delete temp;
stackSize--;
return value;
}
int peek() {
if (isEmpty()) return -1;
return top->data;
}
bool isEmpty() { return top == nullptr; }
int size() { return stackSize; }
};
push():将元素压入栈顶pop():移除栈顶元素top():返回栈顶元素empty():检查栈是否为空size():返回栈中元素个数pop()不返回被删除的元素top()前应确保栈非空stack<int, vector<int>> s;
stack<int, list<int>> s;
#include <iostream>
#include <stack>
usng namespace std;
int main() {
stack<int> s;
// 向栈中添加元素
s.push(10);
s.push(20);
s.push(30);
// 打印栈顶元素
cout << "Top element is: " << s.top() << endl; // 输出: Top element is: 30
// 移除栈顶元素
s.pop();
cout << "After popping, top element is: " << s.top() << endl; // 输出: After popping, top element is: 20
// 检查栈是否为空
if (!s.empty()) {
cout << "Stack is not empty." << endl; // 输出: Stack is not empty.
}
// 打印栈的大小
cout << "Size of stack: " << s.size() << endl; // 输出: Size of stack: 2
// 继续移除元素
s.pop();
s.pop();
// 检查栈是否为空
if (s.empty()) {
cout << "Stack is empty." << endl; // 输出: Stack is empty.
}
return 0;
}
| 特性 | 数组实现 | 链表实现 | STL stack |
|---|---|---|---|
| 内存分配 | 静态/预分配 | 动态分配 | 动态分配 |
| 空间效率 | 可能浪费 | 高效 | 高效 |
| 时间效率 | 操作O(1) | 操作O(1) | 操作O(1) |
| 实现复杂度 | 简单 | 中等 | 最简单(直接使用) |
| 扩展性 | 有限 | 良好 | 良好 |
| 缓存友好性 | 高 | 低 | 中等 |
| 适用场景 | 大小可预测 | 大小不可预测 | 一般用途 |
| 溢出风险 | 有栈溢出风险 | 无栈溢出风险 | 无栈溢出风险 |
选择建议:
示例代码:
void function3() {
int x = 3;
// 函数3的栈帧在最顶部
}
void function2() {
int y = 2;
function3(); // 调用function3
// function3返回后继续执行
}
void function1() {
int z = 1;
function2(); // 调用function2
// function2返回后继续执行
}
int main() {
function1(); // 调用function1
return 0;
}
示例代码:
int evaluateExpression(string expr) {
stack<int> values;
stack<char> ops;
for (int i = 0; i < expr.length(); i++) {
if (isdigit(expr[i])) {
int val = 0;
while (i < expr.length() &&
isdigit(expr[i])) {
val = val * 10 + (expr[i] - '0');
i++;
}
i--;
values.push(val);
}
else if (expr[i] == '(') {
ops.push(expr[i]);
}
else if (expr[i] == ')') {
while (!ops.empty() &&
ops.top() != '(') {
int val2 = values.top();
values.pop();
int val1 = values.top();
values.pop();
char op = ops.top();
ops.pop();
values.push(applyOp(val1, val2, op));
}
ops.pop(); // 弹出'('
}
else if (expr[i] == '+' ||
expr[i] == '-' ||
expr[i] == '*' ||
expr[i] == '/') {
while (!ops.empty() &&
precedence(ops.top()) >=
precedence(expr[i])) {
int val2 = values.top();
values.pop();
int val1 = values.top();
values.pop();
char op = ops.top();
ops.pop();
values.push(applyOp(val1, val2, op));
}
ops.push(expr[i]);
}
}
while (!ops.empty()) {
int val2 = values.top();
values.pop();
int val1 = values.top();
values.pop();
char op = ops.top();
ops.pop();
values.push(applyOp(val1, val2, op));
}
return values.top();
}
示例代码:
bool isValid(string s) {
stack<char> st;
for (char c : s) {
if (c == '(' || c == '{' || c == '[') {
st.push(c);
}
else {
if (st.empty()) return false;
if (c == ')' && st.top() != '(')
return false;
if (c == '}' && st.top() != '{')
return false;
if (c == ']' && st.top() != '[')
return false;
st.pop();
}
}
return st.empty();
}
POJ 1426. Find The Multiple
问题描述:
给定一个括号序列,包含小括号'('和')',判断该序列是否合法。合法的定义是每个左括号都有一个对应的右括号,且括号序列正确嵌套。
解题思路:
完整代码:
#include <iostream>
#include <stack>
#include <string>
using namespace std;
bool isValid(string s) {
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();
}
int main() {
string s;
while (cin >> s) {
if (isValid(s)) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
}
return 0;
}
HDU 1237. 简单计算器
问题描述:
实现一个简单的计算器,支持加减乘除四种运算,没有括号。
解题思路:
示例:
输入:3 + 5 * 2
输出:13
实现代码:
#include <bits/stdc++.h>
using namespace std;
int calculate(string s) {
stack<int> nums;
stack<char> ops;
stringstream ss(s);
int num;
char op;
// 读取第一个数字
ss >> num;
nums.push(num);
while (ss >> op) {
if (op == '0') break;
// 读取下一个数字
ss >> num;
// 根据运算符优先级处理
if (op == '+' || op == '-') {
while (!ops.empty()) {
char top_op = ops.top();
ops.pop();
int b = nums.top(); nums.pop();
int a = nums.top(); nums.pop();
if (top_op == '+') nums.push(a + b);
else if (top_op == '-') nums.push(a - b);
else if (top_op == '*') nums.push(a * b);
else if (top_op == '/') nums.push(a / b);
}
ops.push(op);
} else { // * 或 /
while (!ops.empty() && (ops.top() == '*' || ops.top() == '/')) {
char top_op = ops.top();
ops.pop();
int b = nums.top(); nums.pop();
int a = nums.top(); nums.pop();
if (top_op == '*') nums.push(a * b);
else nums.push(a / b);
}
ops.push(op);
}
nums.push(num);
}
// 处理剩余的运算符
while (!ops.empty()) {
char top_op = ops.top();
ops.pop();
int b = nums.top(); nums.pop();
int a = nums.top(); nums.pop();
if (top_op == '+') nums.push(a + b);
else if (top_op == '-') nums.push(a - b);
else if (top_op == '*') nums.push(a * b);
else if (top_op == '/') nums.push(a / b);
}
return nums.top();
}
int main() {
string s;
while (getline(cin, s) && s != "0") {
cout << calculate(s) << endl;
}
return 0;
}
POJ 2559. 直方图中最大的矩形
问题描述:
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
解题思路:
实现代码:
#include <iostream>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
LL largestRectangleArea(vector<int>& heights) {
stack<int> st;
heights.push_back(0); // 添加哨兵
LL maxArea = 0;
for (int i = 0; i < heights.size(); i++) {
while (!st.empty() && heights[st.top()] > heights[i]) {
int height = heights[st.top()];
st.pop();
int width = st.empty() ? i : i - st.top() - 1;
maxArea = max(maxArea, (LL)height * width);
}
st.push(i);
}
heights.pop_back(); // 移除哨兵
return maxArea;
}
int main() {
int n;
while (cin >> n && n != 0) {
vector<int> heights(n);
for (int i = 0; i < n; i++) {
cin >> heights[i];
}
cout << largestRectangleArea(heights) << endl;
}
return 0;
}
复杂度分析:
CSES 1645. 最近的较小值
问题描述:
给定一个包含n个整数的数组。对于每个位置,找出位于其左侧的第一个比当前值小的元素的位置。如果不存在这样的元素,输出0。
解题思路:
实现代码:
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> arr(n);
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
// 使用pair存储值和索引
stack<pair<int,int>> st;
vector<int> result(n);
for (int i = 0; i < n; i++) {
// 弹出所有大于等于当前值的元素
while (!st.empty() && st.top().first >= arr[i]) {
st.pop();
}
// 如果栈为空,说明左侧没有更小的值
if (st.empty()) {
result[i] = 0;
} else {
// 栈顶元素即为左侧第一个较小值
result[i] = st.top().second + 1;
}
// 将当前元素入栈
st.push({arr[i], i});
}
// 输出结果
for (int i = 0; i < n; i++) {
cout << result[i] << " ";
}
cout << endl;
return 0;
}
示例:
输入:
8
2 5 1 4 8 3 2 5
输出:
0 1 0 3 4 3 3 7
核心要点:
应用场景:
经典例题:
[HDU 1062] Text Reverse
[POJ 1363] Rails
[CSES 1619] Restaurant Customers
[POJ 3250] Bad Hair Day
[HDU 4699] Editor
[CSES 1142] Advertisement
[POJ 2082] Terrible Sets
[CSES 1076] Sliding Median
[CSP-S 2019] 括号序列
[USACO 2016 Feb Gold] Circular Barn
[POJ 1028] Web Navigation
[CSP-J 2022] 解密

演讲者备注不会在演示模式中显示给观众,仅供演讲者参考。 每个关键页面都添加了备注,帮助演讲者更好地讲解内容。
封面页: - 欢迎学生,简要介绍本次课程的主题和目标 - 强调栈在数据结构和算法中的重要性 - 本讲义将从基本概念到实际应用,系统讲解栈的原理和应用
目录页: - 简要介绍讲义结构 - 栈的基本概念、操作、实现、应用、例题等
转场页: - 介绍栈的基本概念 - 引入LIFO原理
栈的定义: - 基础知识介绍 - 与其他数据结构的区别
转场页: - 介绍栈的基本操作 - 引入push、pop等核心操作
转场页: - 介绍栈的不同实现方式 - 数组实现和链表实现的比较
转场页: - 介绍栈的实际应用场景 - 展示栈在编程中的重要性
转场页: - 介绍栈的经典应用例题 - 通过实例加深理解
转场页: - 介绍栈实现的优化技巧 - 提高栈操作的效率
转场页: - 总结栈的核心概念和应用
转场页: - 栈的练习题目
练习题目部分结束,这些题目涵盖了栈的各个难度和应用场景。 鼓励学生尝试解决这些问题,加深对栈的理解。