栈(Stack)详解与模拟实现
前言
在数据结构的学习中,栈(Stack) 是一个非常基础但极其重要的线性结构。它遵循 “后进先出”(LIFO, Last In First Out) 的原则,广泛应用于算法设计、表达式求值、递归转迭代、括号匹配等场景。
本文将从栈的基本概念出发,介绍 Java 中 Stack 类的使用方式,并手把手带你 模拟实现一个简易的栈结构,帮助你深入理解其内部原理。
一、什么是栈
栈是一种特殊的线性表,只允许在一端进行插入和删除操作:
- 栈顶(Top):进行插入(压栈)和删除(出栈)操作的一端。
- 栈底(Bottom):固定的一端,通常不进行操作。
- LIFO 原则:最后入栈的元素最先出栈。
现实生活中的例子:
- 羽毛球桶的羽毛球先进后出
- 函数调用栈(方法嵌套调用)
- 撤销操作(Undo)
二、Java 中的 Stack 类
Java 提供了内置的 java.util.Stack 类,继承自 Vector,是线程安全的动态数组实现。
| 方法 | 功能说明 |
| `Stack()` | 构造一个空栈 |
| `E push(E e)` | 将元素 `e` 压入栈顶,返回该元素 |
| `E pop()` | 弹出并返回栈顶元素(栈为空时抛出异常) |
| `E peek()` | 查看栈顶元素但不移除 |
| `int size()` | 返回栈中元素个数 |
| `boolean empty()` | 判断栈是否为空 |
代码示例:
import java.util.Stack;public class Main {public static void main(String[] args) {Stack<Integer> s = new Stack<>();s.push(1);s.push(2);s.push(3);s.push(4);System.out.println("栈大小: " + s.size()); // 输出 4System.out.println("栈顶元素: " + s.peek()); // 输出 4s.pop(); // 弹出 4System.out.println("弹出后栈顶: " + s.pop()); // 弹出 3,输出 3if (s.empty()) {System.out.println("栈空");} else {System.out.println("当前栈大小: " + s.size()); // 输出 2}}
}三、栈中的函数的模拟实现
设计思路:
- 使用
int[] array存储数据 size记录当前元素个数- 支持动态扩容(类似
ArrayList)
import java.util.Arrays;public class MyStack {private int[] array;private int size;// 构造方法:初始容量为3public MyStack() {array = new int[3];}// 压栈public int push(int e) {ensureCapacity(); // 检查并扩容array[size++] = e;return e;}// 出栈public int pop() {if (empty()) {throw new RuntimeException("栈为空,无法出栈!");}return array[--size];}// 查看栈顶(不删除)public int peek() {if (empty()) {throw new RuntimeException("栈为空,无法获取栈顶元素!");}return array[size - 1];}// 获取栈大小public int size() {return size;}// 判断是否为空public boolean empty() {return size == 0;}// 动态扩容private void ensureCapacity() {if (size == array.length) {array = Arrays.copyOf(array, size * 2);}}
}各函数详解:
1. push(int e)
- 将元素添加到栈顶(即数组末尾)
- 自动扩容:当
size == array.length时,容量翻倍 - 返回压入的元素(与 Java 标准库一致)
2. pop()
- 先检查栈是否为空(避免越界)
- 返回
array[--size]:先减size,再取值 - 实现“删除”效果(逻辑删除,物理数据仍存在但不可见)
3. peek()
- 仅读取栈顶元素,不改变栈结构
- 同样需判空,否则访问
array[-1]会出错
4. size() 与 empty()
size()直接返回计数器empty()判断size == 0,语义更清晰
5. ensureCapacity()
- 私有辅助方法,实现动态扩容
- 使用
Arrays.copyOf()创建新数组并复制旧数据
四、小结
栈虽简单,却是算法与系统设计的基石。在实际开发和面试中,理解栈的本质并能灵活运用,往往能事半功倍。
