【java-数据结构】Java优先级队列揭秘:堆的力量让数据处理飞起来

【java-数据结构】Java优先级队列揭秘:堆的力量让数据处理飞起来
在这里插入图片描述

我的个人主页我的专栏:人工智能领域、java-数据结构、Javase、C语言,希望能帮助到大家!!!点赞👍收藏❤

在这里插入图片描述


在这里插入图片描述

引言

在开发中,尤其是需要处理大量数据或者进行任务调度的场景下,如何高效地管理数据的顺序和优先级是一个至关重要的问题。Java 提供了优先级队列(PriorityQueue),它基于堆(Heap)实现,能够以高效的方式管理数据的优先级。在本文中,我们将深入探讨优先级队列的工作原理,特别是堆的作用,并通过示例代码帮助你更好地理解其应用。

一、什么是优先级队列?

优先级队列(Priority Queue)是一种队列数据结构,其中每个元素都包含一个优先级,队列总是按元素的优先级顺序进行排序。与普通队列(先进先出 FIFO)不同,优先级队列确保每次从队列中移除的元素是具有最高优先级的元素。有些场景下,使⽤队列显然不合适,⽐如:在⼿机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话;初中那会班主任排座位时可能会让成绩好的同学先挑座位。

在 Java 中,PriorityQueue 是基于堆的实现。堆是一种特殊的二叉树结构,满足特定的顺序性质:最大堆保证每个父节点的值大于等于其子节点的值,而最小堆则相反。

二、堆的基本原理

JDK1.8中的PriorityQueue底层使⽤了堆这种数据结构,⽽堆实际就是在完全⼆叉树的基础上进⾏了⼀些调整。具有以下特点:

  • 对于最大堆,父节点的值始终大于或等于子节点的值;
  • 对于最小堆,父节点的值始终小于或等于子节点的值。

2.1 堆的概念

如果有⼀个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全⼆叉树的顺序存储⽅式存储在⼀个⼀维数组中,并满⾜:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为⼩堆(或⼤堆)。
Java 中的 PriorityQueue 默认是最小堆,也就是说队列中最小的元素将具有最高的优先级。

堆的性质:
• 堆中某个节点的值总是不⼤于或不⼩于其⽗节点的值;
• 堆总是⼀棵完全⼆叉树。
在这里插入图片描述

2.2 堆的存储⽅式

从堆的概念可知,堆是⼀棵完全⼆叉树,因此可以层序的规则采⽤顺序的⽅式来⾼效存储,

在这里插入图片描述
注意:对于⾮完全⼆叉树,则不适合使⽤顺序⽅式进⾏存储,因为为了能够还原⼆叉树,空间中必须 要存储空节点,就会导致空间利⽤率⽐较低。

将元素存储到数组中后,可以根据⼆叉树章节的性质5对树进⾏还原。假设i为节点在数组中的下标,则有:
• 如果i为0,则i表⽰的节点为根节点,否则i节点的双亲节点为 (i - 1)/2
• 如果2 * i + 1 ⼩于节点个数,则节点i的左孩⼦下标为2 * i + 1,否则没有左孩⼦
• 如果2 * i + 2 ⼩于节点个数,则节点i的右孩⼦下标为2 * i + 2,否则没有右孩⼦

三、堆操作时间复杂度

操作类型描述时间复杂度
插入元素使用 add()offer() 方法插入元素O(log n)
删除最小元素使用 poll() 方法移除并返回最小元素O(log n)
查看最小元素使用 peek() 方法返回堆顶元素而不移除O(1)
获取堆大小使用 size() 方法返回当前堆的元素数量O(1)
3.1 建堆的时间复杂度

因为堆是完全⼆叉树,⽽满⼆叉树也是完全⼆叉树,此处为了简化使⽤满⼆叉树来证明(时间复杂度本
来看的就是近似值,多⼏个节点不影响最终结果):

在这里插入图片描述

因此:建堆的时间复杂度为O(N)。

四、PriorityQueue 的基本操作

1. PriorityQueue中放置的元素必须要能够⽐较⼤⼩,不能插⼊⽆法⽐较⼤⼩的对象,否则会抛出 ClassCastException异常
2. 不能插⼊null对象,否则会抛出NullPointerException
3. 没有容量限制,可以插⼊任意多个元素,其内部可以⾃动扩容
4. 插⼊和删除元素的时间复杂度为
5. PriorityQueue底层使⽤了堆数据结构
6. PriorityQueue默认情况下是⼩堆—即每次获取到的元素都是最⼩的元素
4.1 插⼊/删除/获取优先级最⾼的元素
在这里插入图片描述


注意:优先级队列的扩容说明:

• 如果容量⼩于64时,是按照oldCapacity的2倍⽅式扩容的
• 如果容量⼤于等于64,是按照oldCapacity的1.5倍⽅式扩容的
•如果容量超过MAX_ARRAY_SIZE,按照MAX_ARRAY_SIZE来进⾏扩容

五、 构造一个最小堆的优先级队列

importjava.util.PriorityQueue;publicclassPriorityQueueExample{publicstaticvoidmain(String[] args){// 创建一个最小堆PriorityQueue<Integer> pq =newPriorityQueue<>();// 添加元素 pq.add(10); pq.add(5); pq.add(15); pq.add(7);// 打印并移除元素while(!pq.isEmpty()){System.out.println(pq.poll());// 依次输出 5, 7, 10, 15}}}

输出:

5 7 10 15 

在这个示例中,PriorityQueue 自动按照最小堆的规则对元素进行排序。每次调用 poll() 方法时,队列中优先级最高的元素(即最小的元素)会被移除。

六、 自定义优先级

假设我们有一个包含多个任务的列表,每个任务有一个优先级,我们希望按优先级顺序处理这些任务。我们可以通过实现 Comparator 接口来自定义优先级。

importjava.util.PriorityQueue;importjava.util.Comparator;classTask{String name;int priority;publicTask(String name,int priority){this.name = name;this.priority = priority;}@OverridepublicStringtoString(){return name +" (Priority: "+ priority +")";}}publicclassCustomPriorityQueueExample{publicstaticvoidmain(String[] args){// 自定义Comparator,按优先级降序排列PriorityQueue<Task> pq =newPriorityQueue<>(newComparator<Task>(){@Overridepublicintcompare(Task t1,Task t2){returnInteger.compare(t2.priority, t1.priority);// 优先级高的排前面}});// 添加任务 pq.add(newTask("Task 1",3)); pq.add(newTask("Task 2",5)); pq.add(newTask("Task 3",1)); pq.add(newTask("Task 4",4));// 打印并移除任务while(!pq.isEmpty()){System.out.println(pq.poll());}}}

输出:

Task 2 (Priority: 5) Task 4 (Priority: 4) Task 1 (Priority: 3) Task 3 (Priority: 1) 

在这个例子中,PriorityQueue 被用来管理多个任务,并按照任务的优先级(从高到低)排序。

. 自定义优先级示例代码解释

步骤代码示例说明
创建优先级队列PriorityQueue<Task> pq = new PriorityQueue<>(new Comparator<Task>() {...});创建一个带有自定义排序规则的优先级队列,按优先级降序排序
添加任务pq.add(new Task("Task 1", 3));向队列中添加一个新任务
打印任务System.out.println(pq.poll());输出并移除队列中的优先级最高(优先级最大)的任务

七、常见堆的应用场景

应用场景说明示例
任务调度根据任务的优先级执行任务,堆帮助管理和调度任务顺序操作系统的调度程序,网络请求调度器
合并多个有序数据流使用堆合并多个已排序的数据流,维持整体有序性合并 k 个有序链表、流式数据处理
实时数据处理动态地从数据流中获取最小/最大值获取最近的数据流中的最大值/最小值,实时计算排名前N的元素
最短路径算法在图算法(如 Dijkstra 算法)中,用堆优化路径的计算Dijkstra 算法,最短路径计算中的优先级队列
K 个最大元素问题找出数组中最大的 K 个元素求数组中前 K 大的元素,堆排序方法

拓展:TOP-K问题:即求数据集合中前K个最⼤的元素或者最⼩的元素,⼀般情况下数据量都⽐较⼤。
⽐如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。
对于Top-K问题,能想到的最简单直接的⽅式就是排序,但是:如果数据量⾮常⼤,排序就不太可取了
(可能数据都不能⼀下⼦全部加载到内存中)。最佳的⽅式就是⽤堆来解决,基本思路如下:
1. ⽤数据集合中前K个元素来建堆

◦ 前k个最⼤的元素,则建⼩堆
◦ 前k个最⼩的元素,则建⼤堆

2. ⽤剩余的N-K个元素依次与堆顶元素来⽐较,不满⾜则替换堆顶元素
将剩余N-K个元素依次与堆顶元素⽐完之后,堆中剩余的K个元素就是所求的前K个最⼩或者最⼤的元素

八、总结

通过本文的介绍,我们了解了 Java 中优先级队列(PriorityQueue)的基本概念和实现原理。利用堆结构,优先级队列能够高效地管理数据并根据优先级进行处理。无论是任务调度、数据流合并,还是实时数据处理,堆都能发挥其强大的性能优势。

8.1 堆的优点
优点说明
高效的优先级管理通过堆结构,可以快速处理数据的优先级。插入和删除操作的时间复杂度为 O(log n),适合动态数据处理。
无序输入,高效排序堆无需输入数据有序,只需通过堆的结构来维护顺序。适用于合并已排序数据流。
内存占用少堆是完全二叉树结构,相比于其他数据结构(如 AVL 树、红黑树)占用的内存较少。
8.2 优先级队列的优势与局限性
优势/局限性说明
优势- 对于频繁插入和删除操作非常高效。
- 适合任务调度、流式数据处理、最短路径问题等场景。
局限性- 不支持按优先级范围查询或批量删除。
- 不是完全通用的排序工具,通常只适用于频繁访问最大或最小元素的场景。
8.3 堆与其他数据结构对比
数据结构操作时间复杂度优势局限性
插入、删除、查看顶元素O(log n)高效管理优先级,适合动态数据处理。不支持按特定条件的排序,无法直接获取中间元素。
数组排序、查找O(n log n)方便查找和排序,简单易用。插入、删除操作较慢,尤其是在无序数据中。
链表插入、删除O(1)插入和删除效率高,尤其适合频繁变动的场景。查找元素需要 O(n) 的时间,无法高效管理优先级。
红黑树插入、删除、查找O(log n)支持高效的查找、插入和删除操作。相较于堆,内存占用更大,且需要更多的平衡操作。
哈希表查找、插入、删除O(1)查找操作极快,适合无序数据的快速检索。不支持排序,不适合优先级管理。
前景:随着大数据和实时计算的不断发展,堆结构和优先级队列将在更多的算法优化和数据流处理中扮演重要角色,尤其是在机器学习、数据挖掘、搜索引擎优化等领域。

Read more

[AI提效-20]-豆包实操指南:高效完成学术论文的搜索与解读(新手也能上手)

学术研究、论文写作中,我们常陷入两大困境:一是找不到精准匹配的权威论文,翻遍知网、万方却被无关文献淹没,浪费大量时间;二是读懂论文难,尤其是英文文献、专业度高的实证论文,面对复杂的研究方法、晦涩的理论表述,半天抓不住核心要点,更无法高效复用其中的研究思路和成果。 其实,借助豆包的AI能力(学术搜索、多模态解读、逻辑梳理、翻译辅助等),就能轻松解决这两大痛点——不用手动筛选文献、不用逐字啃晦涩表述,新手也能在1-2小时内,完成“精准搜论文→快速读论文→吃透核心要点”的全流程,适配本科、硕士论文写作、课题研究等各类学术场景。 本文将手把手教你,如何使用豆包进行学术论文的搜索与解读,从搜索入口定位、精准指令搭建,到论文拆解、要点提炼,每一步都附具体操作和指令模板,直接套用就能提升学术效率,避免无效内耗。 一、先搞懂核心:豆包在学术论文场景的核心优势 很多人只用豆包聊天、问基础问题,却忽略了它的学术赋能能力——相较于传统文献检索工具(知网、万方)

By Ne0inhk
用微信指挥你的 AI 员工:QClaw 给普通人发了一张超级个体的入场券

用微信指挥你的 AI 员工:QClaw 给普通人发了一张超级个体的入场券

昨晚,深圳龙岗区相关部门发布了《深圳市龙岗区支持 OpenClaw&OPC 发展的若干措施(征求意见稿)》公开征询意见公告,也就是大家常说的"龙虾十条"。 大家好,我是小虎。 但当一个地方政府开始为一个开源 AI 项目立专项扶持政策,通常意味着:这件事已经大到用市场语言说不清楚了,必须用政策语言来背书。 OpenClaw 是奥地利开发者 Peter Steinberger 创造的一个开源本地 AI Agent 框架,核心逻辑是把 AI 助手部署在你自己的机器上,通过 Telegram、WhatsApp 这些聊天工具接收指令,然后帮你执行任务。 数据留在本地,算力用自己的,7×24 小时待命。 这个逻辑本身非常先进——但它有一个致命门槛:你得先把它跑起来。 买服务器、命令行配置、设置机器人权限……整个流程对普通人来说不是学习曲线,是一道墙。

By Ne0inhk
腾讯扔出“王炸”|微信变身AI超级入口:Qclaw免费内测,三步上手攻略

腾讯扔出“王炸”|微信变身AI超级入口:Qclaw免费内测,三步上手攻略

文章目录 * 使用教程 过去,大家总觉得AI工具有门槛——要配置环境、学习指令、切换应用,繁琐得像换一台新电脑。 但现在,Qclaw把这一切彻底打破。 从下载到使用,只需三步,全程不超过3分钟。 没有复杂的设置,没有技术门槛,真正做到了“傻瓜式操作,专业级体验”。 第一步:下载安装 前往 Qclaw 官网(https://claw.guanjia.qq.com/),根据你的系统(Mac / Windows)下载安装包,一键安装,无需任何开发环境配置,耗时不到2分钟。 第二步:扫码绑定 打开电脑端 Qclaw,用微信扫描界面上的二维码,30秒内即可完成绑定。 从此,你的微信就成了Qclaw的“远程遥控器”。 第三步:发送指令 在微信里直接对Qclaw说你想做的事——无论是处理文档、操作电脑,还是执行某个具体任务,

By Ne0inhk
AI调参技巧:贝叶斯优化Optuna

AI调参技巧:贝叶斯优化Optuna

AI调参技巧:贝叶斯优化Optuna 📝 本章学习目标:本章聚焦性能优化,帮助读者提升模型效率。通过本章学习,你将全面掌握"AI调参技巧:贝叶斯优化Optuna"这一核心主题。 一、引言:为什么这个话题如此重要 在人工智能快速发展的今天,AI调参技巧:贝叶斯优化Optuna已经成为每个AI从业者必须掌握的核心技能。Python作为AI开发的主流语言,其丰富的生态系统和简洁的语法使其成为机器学习和深度学习的首选工具。 1.1 背景与意义 💡 核心认知:Python在AI领域的统治地位并非偶然。其简洁的语法、丰富的库生态、活跃的社区支持,使其成为AI开发的不二之选。掌握Python AI技术栈,是进入AI行业的必经之路。 从NumPy的高效数组运算,到TensorFlow和PyTorch的深度学习框架,Python已经构建了完整的AI开发生态。据统计,超过90%的AI项目使用Python作为主要开发语言,AI岗位的招聘要求中Python几乎是标配。 1.2 本章结构概览 为了帮助读者系统性地掌握本章内容,我将从以下几个维度展开: 📊 概念解析 → 原理推导 → 代

By Ne0inhk