Java 数据结构基础:栈、堆与 Deque

一、栈(Stack)是什么?

栈是一种数据结构,核心特点是 后进先出(LIFO,Last In First Out) 。

可以把它想象成一摞盘子:最后放上去的盘子,必须最先拿走。

栈的常见操作:

操作 含义
push() 入栈,将元素放到栈顶
pop() 出栈,移除并返回栈顶元素
peek() 查看栈顶元素,但不移除
isEmpty() 判断栈是否为空

例如,依次将 10、20、30 入栈,连续两次出栈,得到的顺序是 30、20。

栈适用于括号匹配、表达式计算、撤销操作等场景。

二、Java 中如何使用栈?

Java 提供了传统的 Stack 类,但刷算法题时,通常更推荐使用 Deque 接口配合 ArrayDeque 实现栈。

arduino 复制代码
import java.util.ArrayDeque;
import java.util.Deque;

Deque<Integer> stack = new ArrayDeque<>();

stack.push(10);
stack.push(20);
stack.push(30);

System.out.println(stack.peek()); // 30
System.out.println(stack.pop());  // 30
System.out.println(stack.pop());  // 20
System.out.println(stack.isEmpty()); // false

为什么推荐 Deque + ArrayDeque?

  1. Stack 是继承自 Vector 的传统类,方法带有同步机制。
  2. ArrayDeque 不需要这些同步操作,在单线程算法题中通常更合适。
  3. Deque 的接口设计更灵活,既可以实现栈,也可以实现队列。

Stack 并非不能使用,只是通常不作为首选。

三、Deque 是什么?

Deque 全称是 Double Ended Queue,即双端队列。

它是一种 Java 接口,允许从队头和队尾添加、删除、查看元素。

操作 队头 First 队尾 Last
添加 addFirst() addLast()
删除并返回 removeFirst() removeLast()
查看但不删除 peekFirst() peekLast()

例如:

arduino 复制代码
Deque<Integer> deque = new ArrayDeque<>();

deque.addFirst(20); // [20]
deque.addLast(30);  // [20, 30]
deque.addFirst(10); // [10, 20, 30]

deque.removeFirst(); // 删除 10
deque.removeLast();  // 删除 30
// 最后剩下 [20]

需要注意,removeFirst() 在队列为空时会抛出异常;pollFirst() 则会返回 null。

四、Deque 和 ArrayDeque 有什么区别?

这是 Java 面向接口编程的一个典型例子。

ini 复制代码
Deque<Integer> stack = new ArrayDeque<>();

其中:

  • Deque 是接口,定义了可以执行哪些操作。
  • ArrayDeque 是实现类,使用可调整容量的数组来实现这些操作。
  • stack 是引用变量,指向实际创建的 ArrayDeque 对象。

这与下面的写法是同样的设计思想:

ini 复制代码
List<Integer> list = new ArrayList<>();

List 是接口,ArrayList 是实现类。

将变量声明为接口类型,可以减少代码对具体实现类的依赖。

五、栈、队列与双端队列的区别

数据结构 添加方式 删除方式 核心特点
栈 Stack 栈顶添加 栈顶删除 后进先出
队列 Queue 队尾添加 队头删除 先进先出
双端队列 Deque 两端均可添加 两端均可删除 两端均可操作

Deque 可以通过不同的操作组合实现栈或队列:

  • 当作栈: 使用 push()、pop()、peek(),这些操作都作用于队头。
  • 当作队列: 使用 offerLast() 添加到队尾,使用 pollFirst() 从队头取出。

六、堆(Heap)与栈(Stack)不是同一种数据结构

虽然中文里经常把它们放在一起说,但堆和栈是两种不同的数据结构。

1. 栈 Stack

  • 核心规则:后进先出。
  • 典型应用:括号匹配、深度优先搜索、方法调用管理。

2. 堆 Heap

通常指一种满足特定顺序性质的树形数据结构,常见的是二叉堆。

  • 最大堆:父节点的值不小于子节点。
  • 最小堆:父节点的值不大于子节点。
  • 典型应用:优先队列、获取最大值或最小值、寻找第 K 大元素。

还要区分数据结构中的堆与 JVM 堆内存:JVM 堆是主要用于存放对象和数组的运行时内存区域,不要求对象按大小排列。

七、LeetCode 20:有效的括号为什么使用栈?

题目要求判断括号是否正确匹配,例如 "{[]}" 是有效的,而 "([)]" 是无效的。

核心原因是:最后出现的左括号,必须最先匹配。

以 "{[]}" 为例:

  1. 遇到 {,入栈。
  2. 遇到 [,入栈。
  3. 遇到 ],检查栈顶是否为 [,匹配成功后出栈。
  4. 遇到 },检查栈顶是否为 {,匹配成功后出栈。
  5. 遍历结束后,栈为空,说明所有括号都匹配成功。

这正好利用了栈的后进先出特性。

核心总结

  • 栈: 后进先出。
  • 堆: 常见为用于优先队列的树形数据结构。
  • Deque: Java 的双端队列接口,也可以用作栈。
  • ArrayDeque: Deque 的一种常用实现。
  • 刷 Java 算法题: 需要栈时,优先使用 Deque<T> stack = new ArrayDeque<>();。
相关推荐
非优秀程序员20 小时前
第04章 邮箱大战,163 与 QQ 的暗战|《互联网产品恩仇录》
java·vue.js·架构
知已难寻21 小时前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器
文丑颜不良啊1 天前
LeetCode2481~2500题目解析
java·leetcode
Flynn Liang1 天前
同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
java·人工智能·大模型·架构设计·spring ai·langchain4j·agentscope
聪明的笨猪猪1 天前
实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑
java·经验分享·面试·ai编程
愿有所息1 天前
记一次 ARM64 + JDK8 上 fastjson2 的诡异数据错乱
java
秋饼1 天前
MCP 2026-07-28 无状态协议大改版:Spring AI 2.1 多轮往返请求与网关路由落地
java·ai·技术分享·后端开发
SL_staff1 天前
JVS-BI 实战:业务人员如何用零代码 ELT + 可视化配置构建实时经营分析闭环
java·spring·全栈
SL_staff1 天前
企业AI落地难?JVS-AI渐进式实践:安全可控、小切口验证、标准化沉淀与规模化复制
java·开源·aigc
SL_staff1 天前
JVS数字底座实践:构建企业级统一内容管理平台的技术路径
java·产品