一、栈的基本概念
栈(Stack)是一种遵循后进先出(LIFO)原则的线性数据结构。它就像一叠盘子,最后放入的盘子总是最先被取出。栈的核心操作包括:
- 压栈(Push):向栈顶添加元素
- 弹栈(Pop):移除栈顶元素
- 查看栈顶(Top):获取栈顶元素但不删除
- 判空(Empty):检查栈是否为空
二、栈的实现方式
1. 数组实现(静态栈)
使用数组存储元素,通过栈顶指针(top)管理栈状态:
template<typename T>
class ArrayStack {
private:
T* data;
int capacity;
int top;
public:
ArrayStack(int size = 10) : capacity(size), top(-1) {
data = new T[capacity];
}
void push(const T& item) {
if (top == capacity - 1) throw std::overflow_error("Stack is full");
data[++top] = item;
}
T pop() {
if (empty()) throw std::underflow_error("Stack is empty");
return data[top--];
}
T top() const {
if (empty()) throw std::underflow_error("Stack is empty");
return data[top];
}
bool empty() const { return top == -1; }
int size() const { return top + 1; }
};
2. 链表实现(动态栈)
通过链表节点动态管理内存:
template<typename T>
class ListNode {
public:
T data;
ListNode* next;
ListNode(const T& val) : data(val), next(nullptr) {}
};
template<typename T>
class ListStack {
private:
ListNode<T>* top;
public:
ListStack() : top(nullptr) {}
void push(const T& item) {
ListNode<T>* newNode = new ListNode<T>(item);
newNode->next = top;
top = newNode;
}
T pop() {
if (empty()) throw std::underflow_error("Stack is empty");
T result = top->data;
ListNode<T>* temp = top;
top = top->next;
delete temp;
return result;
}
T top() const {
if (empty()) throw std::underflow_error("Stack is empty");
return top->data;
}
bool empty() const { return top == nullptr; }
int size() const {
int count = 0;
ListNode<T>* current = top;
while (current) {
count++;
current = current->next;
}
return count;
}
};
三、标准库实现
C++ 标准库提供了stack
容器适配器,默认基于deque
实现:
#include <stack>
#include <iostream>
int main() {
std::stack<int> st;
st.push(10);
st.push(20);
std::cout << st.top() << std::endl; // 输出20
st.pop();
std::cout << st.size() << std::endl; // 输出1
return 0;
}
四、典型应用场景
- 函数调用栈:记录函数调用层级
- 括号匹配:验证括号是否正确闭合
- 表达式求值:中缀表达式转后缀表达式
- 回溯算法:迷宫路径搜索、八皇后问题
- 浏览器前进后退:记录访问历史
五、实现方式对比
特性 | 数组实现 | 链表实现 |
---|---|---|
内存分配 | 静态分配 | 动态分配 |
访问效率 | O(1) | O(1) |
空间利用 | 可能浪费内存 | 按需分配 |
扩展性 | 需要预分配空间 | 动态扩展 |
实现复杂度 | 较低 | 较高 |
六、性能优化建议
- 对于高频操作场景,优先选择数组实现
- 需要动态扩展时,可使用动态数组(如
std::vector
) - 链表实现时注意内存管理,避免内存泄漏
- 大对象存储时考虑智能指针
七、总结
栈是计算机科学中最基础的数据结构之一,其 LIFO 特性使其在程序执行、算法设计等领域发挥着不可替代的作用。通过掌握数组和链表两种实现方式,理解标准库容器的使用方法,能够帮助开发者更高效地解决实际问题。在具体应用中,应根据场景需求选择合适的实现方式,同时注意内存管理和性能优化。