数据结构>>优先级队列(堆)

优先级队列与堆(大根堆详解 + Java实现)

本文讲解优先级队列、堆的底层原理、下标映射规则、建堆、增删改操作,配套 Java 完整代码,适合数据结构复习

一、优先级队列

1. 优先级队列概念

前面学习的普通队列遵循先进先出(FIFO)。

而优先级队列是一种特殊队列:元素出队的依据不是入队先后顺序,而是元素的优先级,优先级高的元素先出队,简单说:谁优先级高,谁先出去。

为什么需要优先级队列?

某些场景下处理的数据带有优先级,需要优先处理高优先级的数据,普通 FIFO 队列就无法满足需求。

举个生活例子:手机正在玩游戏时,有电话打入,操作系统会优先处理电话这个高优先级任务。

这类场景下,数据结构核心需要两个功能:

  • 获取 / 返回当前最高优先级的对象
  • 添加新的对象

具备这两个能力的抽象数据结构,就是优先级队列(Priority Queue)。

Java 中的 PriorityQueue

✅ 物理存储:数组(内存中真实存放数据)

✅ 逻辑结构:完全二叉树(只是逻辑抽象,没有节点、left/right 指针)

✅ 抽象类型:优先级队列(ADT,对外暴露功能)

重点:Java 自带的PriorityQueue底层是数组,逻辑上映射为完全二叉树,默认实现为小根堆,依靠堆的特性实现优先级队列。

二、堆

1. 堆的概念

⚠️ 区分:优先级队列是抽象数据类型,规定 "高优先级先出" 的行为;堆是存储结构。一般用堆实现优先级队列,但是优先级队列 ≠ 堆,不要混淆!

堆:物理上使用数组存储,逻辑上看成一棵完全二叉树,依靠数组下标公式维护父子关系。

2. 堆的两大性质

  1. 结构性质:堆一定是完全二叉树
  2. 堆序性质:分为小根堆、大根堆
  • 小根堆:任意父节点的值 ≤ 左右子节点的值;堆顶(根)是整个堆最小元素

  • 大根堆:任意父节点的值 ≥ 左右子节点的值;堆顶(根)是整个堆最大元素

3. 堆的存储方式

堆逻辑上是完全二叉树,不需要链表节点指针,适合顺序存储(数组存储)。

将元素存入数组后,可以利用完全二叉树的性质由数组还原这棵逻辑上的二叉树。设节点在数组中的下标为 i:

  • 若 i=0,该节点是根节点;否则节点 i 的双亲下标为 (i-1)/2(整数除法向下取整)
  • 若 2i+1 < 节点总数,则节点 i 的左孩子下标为 2i+1,否则无左孩子
  • 若 2i+2 < 节点总数,则节点 i 的右孩子下标为 2i+2,否则无右孩子

4. 堆的创建(Java)

示例数据集合:{ 27,15,19,18,28,34,65,49,25,37 }

Java 自带 PriorityQueue 默认是小根堆,下面我们手动实现大根堆。

建堆核心思路:从最后一个非叶子节点向前遍历,依次执行向下调整(下沉 shiftDown)

向下过程 (以大堆(大根堆)为例):

让 parent 标记需要调整的节点,child 标记 parent 的左孩子 (注意:parent 如果有孩子一定先是有左孩子)

如果 parent 的左孩子存在,即:child < size, 进行以下操作,直到 parent 的左孩子不存在

parent 右孩子是否存在,存在找到左右孩子中最大的孩子,让 child 进行标记

将 parent 与较大的孩子 child 比较,如果:

parent 大于等于较大的孩子 child,调整结束

否则:交换 parent 与较大的孩子 child,交换完成之后,parent 中小的元素向下移动,可能导致子树不满足堆的性质,因此需要继续向下调整,即 parent = child;child = parent*2+1; 然后继续。

循环完成所有非叶子节点下沉之后,整个数组就满足大根堆性质。

三、堆的其他操作(增删改查)

1. 堆的插入(增)

插入思路:

把新元素放在完全二叉树最后的位置(数组usedSize下标处),然后执行向上调整(上浮 shiftUp),向上比较交换,维持大根堆性质。

2. 堆的删除(删)

堆默认只删除堆顶元素

删除思路:

交换堆顶元素和最后一个有效元素,有效元素数量减一,然后对新的堆顶执行向下调整(下沉 shiftDown)。

3. 堆的修改(改)

修改堆顶元素:更新堆顶值之后,从根节点开始向下调整。

拓展:如果修改任意下标位置元素:大根堆中,新值更大 → 上浮;新值更小 → 下沉

4. 堆的查看(查)

直接返回堆顶elem0;操作前先判断堆是否为空。

具体的代码实现:Java20261022 · 若亦/代码仓库 - 码云 - 开源中国

相关推荐
Wang's Blog1 小时前
Java 项目实战: 交友项目 - 查询圈子个人动态:查询我的动态需求分析
java·开发语言·交友
denlaku1 小时前
JDK 23 新特性详解
java
code2cat1 小时前
Java高级篇之Hibernate:让对象映射到表,理解持久化与事务
java·后端·hibernate·1024程序员节
bksczm2 小时前
Redis数据结构之hash
数据结构·redis·哈希算法·1024程序员节
骑着蜗牛撵大象3272 小时前
飞牛fnOS部署Damselfly:Compose编排、照片目录与7100固定访问
java·docker·rpc·dubbo·fnos·照片管理·damselfly
金銀銅鐵3 小时前
[Java] 用 CLI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
Nuanyt3 小时前
Hot 100 刷题笔记 · 数组与哈希专题(3 题)
java·笔记·算法·leetcode·哈希算法·1024程序员节
xieliyu.3 小时前
【JavaEE进阶】Spring Boot 日志:从 System.out 到 @Slf4j,6 个级别 + 4 类配置一篇讲透
java·spring boot·spring·java-ee·springboot·logback·slf4j
IT_Octopus4 小时前
Apollo 配置中心入门:一所“小学校“读懂 Portal、Meta Server、Config Service
java·后端·spring