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<>();。
相关推荐
牛战士coding1 小时前
用户点了停止生成,上游还在烧 token 吗?取消传播链路拆解
java·人工智能
初心未改HD1 小时前
DSH Skill开发实战:SKILL.md是给LLM看的操作手册,不是给人看的README,踩了4个坑
java·大数据·开发语言
aibo8603081 小时前
基于 Spring Boot 的茶铺管理系统设计与实现
java·spring boot·后端
Wang's Blog1 小时前
Java 项目实战: 交友项目 - SpringData-Mongo 环境搭建和 CRUD
java·开发语言·交友
SunnyDays10112 小时前
Java 操作 PPT 超链接:添加、修改和删除
java·powerpoint·ppt·超链接
Thomas.Sir2 小时前
第4课:配置文件详解:application.yml/properties,多环境配置、配置分组、配置校验
java·spring boot
白露与泡影2 小时前
一线 Java 后端面试八股(2026 更新版,含完整答案)
java·开发语言·面试
SL_staff2 小时前
APS落地失败的5个隐形坑:离散制造排产为何总在Excel里打转?
java·人工智能·开源
Code-zyc2 小时前
读取电表数据并展示
java