【优先级队列PriorityQueue】

目录

1,优先级队列

1.1 概念

2,优先级队列的模拟实现

2.1 堆的概念

2.2 堆的存储方式

2.3 堆的创建

2.3.1 堆的向下调整(大根堆)

2.3.2 建堆的时间复杂度​编辑

2.4 堆的插入与删除

2.4.1 堆的插入

2.4.2 堆的删除

3,常用接口介绍

3.1 PriorityQueue的特性

3.2 PriorityQueue常用接口介绍

3.2.1 优先级队列的构造

3.2.2 插入/删除/获取优先级最高的元素

3.2.3 PriorityQueue的大根堆,小根堆转换

3.2.4 PriorityQueue的扩容方式

3.3 oj练习

3.3.1 top-k问题

3.3.2 求一组数据第k小的元素

3.3.3 求一组数据第k大的元素

4,堆的应用

4.1 堆排序        


1,优先级队列

1.1 概念

前面介绍过队列,队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列,该中场景下,使用队列显然不合适,比如:在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话;初中那会班主任排座位时可能会让成绩好的同学先挑座位。

在这种情况下,数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。

2,优先级队列的模拟实现

JDK1.8中的PriorityQueue底层使用了堆这种数据结构,而堆实际就是在完全二叉树的基础上进行了一些调整。

2.1 堆的概念

如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一 个一维数组中,并满足:Ki = K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆

堆的性质:

堆中某个节点的值总是不大于或不小于其父节点的值

堆总是一棵完全二叉树。

2.2 堆的存储方式

从堆的概念可知,堆是一棵完全二叉树,因此可以层序的规则采用顺序的方式来高效存储。

上图,对于非完全二叉树,则不适合使用顺序方式进行存储,因为为了能够还原二叉树,空间中必须要存储空节点,就会导致空间利用率比较低。

如果i为0,则i表示的节点为根节点,否则i节点的双亲节点为 (i - 1)/2

如果2 * i + 1 小于节点个数,则节点i的左孩子下标为2 * i + 1,否则没有左孩子

如果2 * i + 2 小于节点个数,则节点i的右孩子下标为2 * i + 2,否则没有右孩子

2.3 堆的创建

2.3.1 堆的向下调整(大根堆)

因为是以数组存储的,先创建好数组。

此时数组elem中存储的数据为:{27,15,19,18,28,34,65,49,25,37}

从二叉树的角度来看,是这样的:

调整成大根堆:

注意:在调整以parent为根的二叉树时,必须要满足parent的左子树和右子树已经是堆了才可以向下调整。 时间复杂度分析:

最坏的情况即图示的情况,从根一路比较到叶子,比较的次数为完全二叉树的高度,即时间复杂度为O(log以2为底的N)

2.3.2 建堆的时间复杂度

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

2.4 堆的插入与删除

2.4.1 堆的插入

上面已经建立好大根堆了,现在要对他进行插入和删除

比如:我们插入一个80,插入完成以后也要保证他是一个大根堆

因为我们操作的是数组,首先得判断是否已满,满了进行扩容

所以我们就可以通过offer元素来创建大根堆,这是向上调整

创建大根堆的方式可以在一个数组已经给定的情况下,在数组内进行调整(向下调整)

也可以一个一个元素offer进行调整成大根堆(向上调整)

所以向上调整的时间复杂度是很高的

2.4.2 堆的删除

如果说现在是一个大根堆,要删除一个元素,删除的是堆顶元素(优先级队列,优先拿到的堆顶元素),删除一个元素之后,也要保证他还是一个大根堆

删除逻辑:

习题:

3,常用接口介绍

3.1 PriorityQueue的特性

Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,本文主要介绍PriorityQueue。

关于PriorityQueue的使用要注意:

1. 使用时必须导入PriorityQueue所在的包,即:

2. PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出 ClassCastException异常

假如有一个学生类:              没有说明两个Student根据什么比较,所以之前讲过自定义类型,要实现Comperable接口 

3. 不能插入null对象,否则会抛出NullPointerException

4. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容

但是没有容量限制,不是说无线可以往里面放,堆是有大小的

5. 插入和删除元素的时间复杂度为O(log以2为底的N),因为插入以后是向上调整,最多调整的是树的高度,删除也是,第一个和最后一个换,最坏情况0下标一直向下调整,也是树的高度

6. PriorityQueue底层使用了堆数据结构

7. PriorityQueue默认情况下是小堆---即每次获取到的元素都是最小的元素

3.2 PriorityQueue常用接口介绍

3.2.1 优先级队列的构造

那么不能是大根堆吗? 答:可以,后面会讲到

此时呢,我们调用的是不带参数的构造方法,进入源码

源码:

代表只要实现Collection接口的,也就是说Collection接口能引用的对象都能接收

3.2.2 插入/删除/获取优先级最高的元素

3.2.3 PriorityQueue的大根堆,小根堆转换

首先进入offer源码:

上面讲过:我们通过不带参数的构造方法,会给queue分配一个长度大小为11的数组

此时数组长度为11,那么我们第一次放一个数据为10

第二次offer,比如是5

对于上图的CompareTo,只要你插入的元素没有你原来的元素大,就会发生交换!!!

所以和CompareTo的实现有关系

换句话说,如果把if里面的比较改成<=0,那就不一样了

可以看到,这是一个大根堆。

所以,CompareTo实现的方式不一样,就可以控制他是大根堆还是小根堆

现在,我们放的是Integer

进入他的源码:他是实现了Comparable接口的,compareTo自己实现了compare方法

那么回到siftUpComparable

PriorityQueue默认是小根堆,就是因为在调用compareTo的时候比较方式来决定的。

那如果说变成大根堆,我们就可以在自己传入一个比较器

如果说传comparator,只需要把if里面的比较改成<=0,换句话说现在把下面代码变成大根堆

就要自己去传一个比较器

当我们自己实现一个比较器的时候,siftDown方法会走if语句

在这种情况下就是小根堆。

当我们改一下比较器的传值

所以,我们就可以把优先级队列看作是小根堆,也可以看作是大根堆,去控制compare的返回值

3.2.4 PriorityQueue的扩容方式

进入offer源码:

当 i >= 11了,数组长度是11,也就是数组满了,满了以后进行扩容

那我们来看一下这里的扩容,进入grow的源码: 

在JDK1.8中,申请数组的最大长度:Integer.MAX_VALUE(21亿多)- 8 

优先级队列的扩容说明:

如果容量小于64时,是按照oldCapacity的2倍方式扩容的

如果容量大于等于64,是按照oldCapacity的1.5倍方式扩容的

如果容量超过MAX_ARRAY_SIZE,按照MAX_ARRAY_SIZE来进行扩容

3.3 oj练习

3.3.1 top-k问题

TOP-K问题:即求数据集合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。

比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。

此时并没有什么问题,代码可以通过。但是不是非常好的解决方案!!!

时间复杂度:

所以这不是真正topK的真正解法!!!

那么如何解决,怎样的解决方式才能实现很小的时间复杂度? 

面试经常问到!!!重点!!!是堆的一个应用!!!

做法:

在这种题里面,往往k是一个很小的数,理论上认为他的时间复杂度为:O(N)

3.3.2 求一组数据第k小的元素

3.3.3 求一组数据第k大的元素

4,堆的应用

4.1 堆排序        

建堆的时间复杂度:O(N),排序的时间复杂度:O(n*logN)

习题:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3224226.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Github Actions 构建Vue3 + Vite项目

本篇文章以自己创建的项目为例&#xff0c;用Github Actions构建。 Github地址&#xff1a;https://github.com/ling08140814/myCarousel 访问地址&#xff1a;https://ling08140814.github.io/myCarousel/ 具体步骤&#xff1a; 1、创建一个Vue3的项目&#xff0c;并完成代…

Sentinel-1 Level 1数据处理的详细算法定义(二)

《Sentinel-1 Level 1数据处理的详细算法定义》文档定义和描述了Sentinel-1实现的Level 1处理算法和方程&#xff0c;以便生成Level 1产品。这些算法适用于Sentinel-1的Stripmap、Interferometric Wide-swath (IW)、Extra-wide-swath (EW)和Wave模式。 今天介绍的内容如下&…

澳大利亚TikTok直播为什么需要海外直播专线?

近年来&#xff0c;许多卖家为了解决澳大利亚TikTok直播中的卡顿和高延迟问题&#xff0c;纷纷选择使用海外直播专线。这种专线服务是一种高效、低延迟的数据传输解决方案&#xff0c;专为需要高质量网络连接的场合设计。 与公共互联网相比&#xff0c;海外直播专线提供更稳定、…

基于深度学习的电影推荐系统

1 项目介绍 1.1 研究目的和意义 在电子商务日益繁荣的今天&#xff0c;精准预测商品销售数据成为商家提升运营效率、优化库存管理以及制定营销策略的关键。为此&#xff0c;开发了一个基于深度学习的商品销售数据预测系统&#xff0c;该系统利用Python编程语言与Django框架&a…

ubuntu使用kubeadm搭建k8s集群

一、卸载k8s kubeadm reset -f modprobe -r ipip lsmod rm -rf ~/.kube/ rm -rf /etc/kubernetes/ rm -rf /etc/systemd/system/kubelet.service.d rm -rf /etc/systemd/system/kubelet.service rm -rf /usr/bin/kube* rm -rf /etc/cni rm -rf /opt/cni rm -rf /var/lib/etcd …

兼容性报错--调整字符集解决

文章目录 错误解决办法Unicode 字符集(两个字节来表示一个字符)多字节字符集(一个字节来表示一个字符)如何选择字符集char与wchar_t的区别LPCSTR与LPCWSTR的区别 错误 解决办法 切换字符集类型 Unicode 字符集(两个字节来表示一个字符) 优点&#xff1a; 支持更多的字符集…

打开excel时弹出stdole32.tlb

问题描述 打开excel时弹出stdole32.tlb 如下图&#xff1a; 解决方法 打开 Microsoft Excel 并收到关于 stdole32.tlb 的错误提示时&#xff0c;通常意味着与 Excel 相关的某个组件或类型库可能已损坏或不兼容。 stdole32.tlb 是一个用于存储自动化对象定义的类型库&#x…

匈牙利汽车市场研究报告(2024版)

匈牙利加入欧盟后成为欧洲国家的汽车制造组装基地和大型跨国企业的零部件供应商&#xff0c;具有深厚的汽车工业基础。在欧债危机后&#xff0c;匈牙利政府提出“向东发展”战略&#xff0c;并将电动化作为汽车行业新的发展方向&#xff0c;通过一系列外资友好政策吸引中日韩等…

2,区块链、数字货币及其应用场景(react+区块链实战)

2&#xff0c;区块链、数字货币及其应用场景&#xff08;react区块链实战&#xff09; 一、什么是区块链&#xff1f;1 ibloackchain&#xff08;1&#xff09;安装ibloackchain&#xff08;2&#xff09;Blance查询余额&#xff08;3&#xff09;Mine挖矿&#xff08;4&#x…

【学术会议征稿】第五届大数据、人工智能与物联网工程国际会议

第五届大数据、人工智能与物联网工程国际会议 2024 5th International Conference on Big Data, Artificial Intelligence and Internet of Things 第五届大数据、人工智能与物联网工程国际会议&#xff08;ICBAIE 2024&#xff09;定于2024年10月25-27号在中国深圳隆重举行。…

Java PKI Programmer‘s Guide

一、PKI程序员指南概述 PKI Programmer’s Guide Overview Java认证路径API由一系列类和接口组成&#xff0c;用于创建、构建和验证认证路径。这些路径也被称作认证链。实现可以通过基于提供者的接口插入。 这个API基于密码服务提供者架构&#xff0c;这在《Java密码架构参考指…

Milvus核心组件(1)

cluster 模式 上一篇其实已经说过 standalone 模式&#xff0c;其实集群模式大同小异&#xff0c;只是在不同机子间使用Kafka或者其他消息中间件保证数据及逻辑的一致性。 Log Broker&#xff0c;如Pulsar这样的系统&#xff0c;是专门设计来处理和管理日志数据的中间件。它主…

【IMU】 温度零偏标定

温度标定 IMU的零偏随着温度的变化而变化&#xff0c;在全温范围内形状各异&#xff0c;有些可能是单调的&#xff0c;有些可能出现拐点。 多项式误差温度标定 目的是对估计的参数进行温度补偿&#xff0c;获取不同温度时的参数值&#xff08;零偏、尺度、正交&#xff09;&…

程序员日志之DNF手游强化20攻略

目录 传送门正文日志1、概要2、炭的获取3、强化 传送门 SpringMVC的源码解析&#xff08;精品&#xff09; Spring6的源码解析&#xff08;精品&#xff09; SpringBoot3框架&#xff08;精品&#xff09; MyBatis框架&#xff08;精品&#xff09; MyBatis-Plus SpringDataJP…

QT案例-通过QCustomPlot库绘制Window系统CPU温度实时折线图

之前项目中涉及到了获取硬件信息内容&#xff0c;对CPU的温度监控有点兴趣&#xff0c;观察和百度发现鲁大师和驱动人生的CPU温度监控貌似是用驱动实现的&#xff0c;有点太高大上了&#xff0c;搞不懂。后面经过到处查找资料终于找到了Qt在Windows 环境下监控CPU等硬件温度/运…

2024年浙江省高考分数一分一段数据可视化

下图根据 2024 年浙江高考一分一段表绘制&#xff0c;可以看到&#xff0c;竞争最激烈的分数区间在620分到480分之间。 不过&#xff0c;浙江是考两次取最大&#xff0c;不是很有代表性。看看湖北的数据&#xff0c;580分到400分的区段都很卷。另外&#xff0c;从这个图也可以…

Java项目:基于SSM框架实现的中小型企业财务管理系统【ssm+B/S架构+源码+数据库+答辩PPT+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的中小型企业财务管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单…

【方法】如何打开设置了密码的ZIP文件?

对于重要的ZIP文件&#xff0c;很多人会设置密码保护&#xff0c;那要如何打开设置了密码的ZIP文件呢&#xff1f;今天我们一起来看下&#xff0c;在记得密码和忘记密码的情况下&#xff0c;如何打开ZIP文件。 情况1&#xff1a; 如果知道ZIP文件原本设置的密码&#xff0c;我…

tessy 单元测试:小白入门指导手册

目录 1,创建单元测试工程目录 2,导入单元测试源文件 一:创建测试文件夹(最好和代码目录一一对应,方便查找) 二:选择测试环境 三:添加源文件 四:分析源文件 3,编写单元测试用例 一:设置函数参数的传输方向 二:添加单元测试用例 三:编辑单元测试用例数据 …

Qt开发 | Qt绘图技术 | 常见图像绘制 | Qt移动鼠标绘制任意形状 | Qt绘制带三角形箭头的窗口

文章目录 一、基本绘图技术介绍二、常见的18种图形、路径、文字、图片绘制三、Qt移动鼠标绘制任意形状四、Qt绘制带三角形箭头的窗口 一、基本绘图技术介绍 Qt提供了绘图技术&#xff0c;程序员可以在界面上拖动鼠标&#xff0c;或者在代码里指定参数进行绘图。 Qt绘图技术介绍…