Java 中 PriorityQueue 的底层数据结构及相关分析

server/2025/3/26 5:43:29/

Java 中 PriorityQueue 的底层数据结构及相关分析

1. PriorityQueue 的底层数据结构

在 Java 中,PriorityQueue 的底层数据结构基于堆(Heap)实现的二叉堆(Binary Heap),默认使用最小堆(Min Heap),即堆顶元素是队列中的最小元素。

PriorityQueue 采用数组(Object[])**来存储数据,并使用**二叉堆结构来维护优先级关系。

2. PriorityQueue 的实现原理

2.1 插入(offer/add)

  • 新元素插入到堆的末尾(数组的最后一个位置)。
  • 通过**上浮(siftUp)**操作,确保堆的有序性。
  • 上浮操作通过比较当前节点与其父节点的大小,若当前节点比父节点小,则交换它们,直到满足最小堆的性质。

2.2 删除(poll/remove)

  • 删除堆顶元素(最小元素)。
  • 用堆的最后一个元素填补堆顶位置。
  • 通过**下沉(siftDown)**操作,确保堆的有序性。
  • 下沉操作通过比较当前节点与其子节点的大小,若当前节点大于子节点,则交换它们,直到满足最小堆的性质。

2.3 获取堆顶元素(peek)

  • 直接返回数组的第一个元素(堆顶)。
  • 时间复杂度 O(1)

2.4 复杂度分析

  • 插入(offer/add):O(log n)
  • 删除(poll/remove):O(log n)
  • 访问堆顶元素(peek):O(1)

3. PriorityQueue 的应用场景

  1. 任务调度(按优先级处理任务)
  2. Dijkstra 最短路径算法
  3. Top K 问题(获取前 K 个最大/最小元素)
  4. 流式数据处理(如实时求中位数)
  5. 操作系统进程调度(按照优先级处理不同任务)
  6. 数据合并(如合并多个有序数组)

4. PriorityQueue 的优缺点

4.1 优点

  • 自动维护有序性,取最小/最大元素效率高。
  • 插入、删除操作高效,时间复杂度 O(log n)
  • 基于堆的高效实现,适用于大量数据的优先级处理。

4.2 缺点

  • 不支持随机访问,不能像 ArrayList 一样通过索引直接访问。
  • 只保证堆顶元素是最小/最大,无法保证整体有序。
  • 非线程安全,如需多线程使用,可考虑 PriorityBlockingQueue

5. 替代方案

需求替代方案
需要线程安全的优先队列PriorityBlockingQueue
需要基于平衡二叉树的优先队列TreeSet(红黑树)
需要维护多个优先级队列ConcurrentSkipListSet(跳表)
需要自定义排序规则TreeMap

6. PriorityQueue 使用示例

6.1 基本用法

java">import java.util.PriorityQueue;public class PriorityQueueExample {public static void main(String[] args) {// 创建最小堆PriorityQueue<Integer> pq = new PriorityQueue<>();pq.offer(5);pq.offer(1);pq.offer(3);pq.offer(7);pq.offer(2);// 依次取出最小元素while (!pq.isEmpty()) {System.out.println(pq.poll());}}
}

输出:

1
2
3
5
7

6.2 自定义排序(最大堆)

java">import java.util.Collections;
import java.util.PriorityQueue;public class MaxHeapExample {public static void main(String[] args) {PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());maxHeap.offer(5);maxHeap.offer(1);maxHeap.offer(3);maxHeap.offer(7);maxHeap.offer(2);while (!maxHeap.isEmpty()) {System.out.println(maxHeap.poll());}}
}

输出:

7
5
3
2
1

6.3 自定义对象排序

java">import java.util.PriorityQueue;
import java.util.Comparator;class Task {String name;int priority;public Task(String name, int priority) {this.name = name;this.priority = priority;}@Overridepublic String toString() {return name + " (Priority: " + priority + ")";}
}public class TaskScheduler {public static void main(String[] args) {PriorityQueue<Task> taskQueue = new PriorityQueue<>(Comparator.comparingInt(t -> t.priority));taskQueue.offer(new Task("Task A", 3));taskQueue.offer(new Task("Task B", 1));taskQueue.offer(new Task("Task C", 2));while (!taskQueue.isEmpty()) {System.out.println(taskQueue.poll());}}
}

输出:

Task B (Priority: 1)
Task C (Priority: 2)
Task A (Priority: 3)

7. 总结

  1. 底层结构:基于二叉堆,使用数组存储。
  2. 操作复杂度:插入/删除 O(log n),访问 O(1)
  3. 应用场景:任务调度、最短路径、Top K 等。
  4. 优缺点:自动排序但不支持随机访问,非线程安全。
  5. 替代方案:线程安全用 PriorityBlockingQueue,基于红黑树用 TreeSet

PriorityQueue 是 Java 中处理优先级任务的高效工具,在需要动态维护最小或最大元素的场景下非常有用。


http://www.ppmy.cn/server/177159.html

相关文章

MySQL-sql优化

插入数据 insert优化 批量插入 insert into tb_users values (1,cat),(2,mouse),(3,bird); 手动提交事务 因为MySQL中默认的事务提交方式为自动提交&#xff0c;所以在每次插入数据时&#xff0c;就是涉及到事务频繁地开启和关闭。所以将事务提交方式改成自动提交&#xf…

wps字符很分散

出现的问题图 alt enter开启自动换行即可解决 检查全局自动换行设置 在 WPS 表格中&#xff0c;点击 ​​“文件”​ → ​​“选项”​ → ​​“高级”​ → 确保 ​​“自动换行”​ 选项开启。 ​使用快捷键快速调整 ​启用自动换行&#xff1a;选中文本后按 ​Alt Enter…

IDEA编码实用技巧

快速注释 Ctrl / 可以将选中的代码或者光标所在的那一行变为用//注释 Ctrl Shift / 可以将选中的代码或者光标所在的那一行变为用/**/注释 移动代码 Alt Shift 上下键 移动该行代码 移动 Ctrl enter&#xff08;回车&#xff09;将光标下面的代码都往下移动一行&a…

用 pytorch 从零开始创建大语言模型(四):从零开始实现一个用于生成文本的GPT模型

从零开始创建大语言模型&#xff08;Python/pytorch &#xff09;&#xff08;四&#xff09;&#xff1a;从零开始实现一个用于生成文本的GPT模型 4 从零开始实现一个用于生成文本的GPT模型4.1 编写 L L M LLM LLM架构4.2 使用层归一化对激活值进行标准化4.3 使用GELU激活函数…

IS-IS原理与配置

一、IS-IS概述 IS-IS&#xff08;Intermediate System to Intermediate System&#xff0c;中间系统到中间系统&#xff09;是ISO&#xff08;International Organization for Standardization&#xff0c;国际标准化组织&#xff09;为它的CLNP&#xff08;ConnectionLessNet…

Vivado 2017.4 impl时,关于DDR dm信号属性设置报严重警告的问题

为了方便测试&#xff0c;针对A板的硬件开发了FPGA代码&#xff0c;由于A板加工周期较长&#xff0c;无法按照正程流程进入调试。使用与A板相同FPGA型号的B板进行调试&#xff0c;A板与B板大部分外设相同&#xff0c;区别可能是管脚约束不一样。 A板和B板的DDR管脚是不相同的&a…

使用 Apktool 反编译、修改和重新打包 APK

使用 Apktool 反编译、修改和重新打包 APK 在 Android 逆向工程和应用修改过程中&#xff0c;apktool 是一个强大的工具&#xff0c;它允许我们解包 APK 文件、修改资源文件或代码&#xff0c;并重新打包成可安装的 APK 文件。本文将介绍如何使用 apktool 进行 APK 反编译、修…

问题链的拓扑学重构

问题链拓扑学重构 目录 概念框架与理论基础综合知识图谱&#xff08;Mermaid 图示&#xff09;核心构成要素与参数解析逻辑链条方法论详解与数学模型 4.1 根源溯源 —— 分形式 5 Whys 与 RCA4.2 网络建模 —— 系统动力学与贝叶斯网络4.3 维度跃迁 —— 第一性原理与跨模态映…