当前位置: 首页 > article >正文

Java优先级队列PriorityQueue

概述

        优先级队列PriorityQueue是队列接口Queue的一种实现,能够以O(logn)的时间复杂度实现元素的插入和删除。PriorityQueue不是一个标准的队列,因为它保存元素的顺序不是按照元素入队的顺序,而一个是按元素的大小重新排序的,这已经违反了队列先进先出(FIFO)的基本规则。PriorityQueue是一种具有特殊用途的数据结构,它总能保持队首元素是队列中最大的,这个特性使得PriorityQueue在需要基于优先级处理任务的场景下非常有用,比如在调度算法、事件驱动编程、优先级排序等应用中。

        想要每次都能从队列中获取最大元素通常能想到的方式有两种:比如元素无序保存,出队时遍历一遍队列找出最大元素,这种方式元素入队的时间复杂度为O(1),出队的时间复杂度为O(n);或者是元素按顺序保存,出队时直接取队首元素,这种方式元素入队的时间复杂度为O(n),出队的时间复杂度为O(1);由于这两种方式都不能兼顾元素入队出队的效率,于是便有了基于二叉堆的实现方式。

完全二叉堆

        PriorityQueue内部实现通常采用堆数据结构,具体来说,是一个完全二叉堆,它在结构上是完全二叉树的形式,也就是说,除了最后一层可能不满外,每一层都是完全填充的,且最后一层的所有结点都尽可能地靠左排列。完全二叉堆分为两种类型:最大堆和最小堆。

最大堆:在最大堆中,每个父节点的值都大于或等于其子节点的值。因此,堆的根节点总是包含堆中的最大值。

最小堆:在最小堆中,每个父节点的值都小于或等于其子节点的值。所以,堆的根节点存储的是堆中的最小值。

        完全二叉堆主要操作包括元素插入和删除:插入的新元素总是被添加到完全二叉树的最后一层的最右侧的空位置,然后通过上滤(swim)过程调整堆,以维护堆的性质。删除操作通常涉及移除堆顶元素,然后将堆的最后一个元素移动到堆顶位置填补空缺,并通过下滤(sink)过程调整堆。完全二叉堆由于其高效的特性(插入和删除O(logn)时间复杂度),常被用于实现优先队列等数据结构和各种算法中,比如堆排序、TopN问题等。堆的详细介绍请参考数据结构:堆

优先级队列的使用

PriorityQueue简单示例:
// 创建一个空的优先级队列
PriorityQueue<Integer> queue = new PriorityQueue<>();
// 添加元素
queue.offer(5);
queue.offer(3);
queue.offer(7);
queue.offer(1);
// 元素出队
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());

输出为1、3、5、7。元素插入是无序的,输出按从小到大排序,可见这是一个最小堆实现的优先队列,也可以通过向构造器传入参数实现降序排序。

定制排序:
// 创建一个空的优先级队列并传入排序规则
PriorityQueue<Integer> queue = new PriorityQueue<>(Comparator.reverseOrder());
// 添加元素
queue.offer(5);
queue.offer(3);
queue.offer(7);
queue.offer(1);
// 元素出队
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
//输出为7、5、3、1
使用集合初始化优先队列:
//创建一个优先级队列并使用List初始化
PriorityQueue<Integer> queue1 = new PriorityQueue<>(Arrays.asList(3,1,7,5));
//创建一个优先级队列并使用另一个队列初始化
PriorityQueue<Integer> queue2 = new PriorityQueue<>(queue1);
//创建一个优先级队列并使用set集合初始化
Set<Integer> set = new HashSet<>();
PriorityQueue<Integer> queue3 = new PriorityQueue<>(set);

Java标准库中实现了多种PriorityQueue的构造器,能够通过不同类型的集合快速地生成一个优先级队列,为程序员提供了便利,提升了应用开发的灵活性。

总结

PriorityQueue不遵循传统队列的FIFO原则,作为一种特殊的队列类型,它通过动态调整元素顺序,高效地支持了基于优先级的操作,是解决特定类型问题的强大工具。


http://www.kler.cn/a/312555.html

相关文章:

  • Node.Js+Knex+MySQL增删改查的简单示例(Typescript)
  • 微服务架构面试内容整理-SpringCloud Netflix‌与Spring Cloud Alibaba比较
  • Python如何从HTML提取img标签下的src属性
  • Android OpenGL ES详解——纹理:纹理过滤GL_NEAREST和GL_LINEAR的区别
  • F5全新报告揭示AI时代API安全面临严峻挑战
  • 动态规划与贪心算法:核心区别与实例分析
  • 大数据Flink(一百二十二):阿里云Flink MySQL连接器介绍
  • 将阮一峰老师的《ES6入门教程》的源码拷贝本地运行和发布
  • 【深度学习】注意力机制介绍,了解什么是注意力计算规则以及常见的计算规则,知道注意力机制的工作流程
  • Linux 基础入门操作-实验一 GCC使用
  • 优化 Elasticsearch 集群性能:解决节点压力不均衡问题及分片策略调整
  • git统计代码行数、提交数
  • 每日OJ题_牛客_WY22 Fibonacci数列(斐波那契)
  • 解决uniapp视频video组件进入全屏再退出全屏后,cover-view失效的问题
  • C++——用选择法对10个数值进行排序。
  • 即时通讯框架MobileIMSDK的H5端开发快速入门
  • Python数据分析案例60——扩展变量后的神经网络风速预测(tsfresh)
  • 系统架构设计师:系统架构设计
  • etcd二次封装
  • Docker上安装mysql
  • MySQL在大数据场景应用
  • 代码随想录训练营 Day60打卡 图论part10 SPFA算法 Bellman-Ford 之判断负权回路 Bellman-Ford 之单源有限最短路
  • vue常用业务场景
  • 通过springcloud gateway优雅的进行springcloud oauth2认证和权限控制
  • Python编码系列—Python代理模式:为对象赋予超能力的魔法
  • QTcpSocket和QLocalSocket详解