转自:https://baijiahao.baidu.com/s?id=1665383380422326763&wfr=spider&for=pc

最近在刷力扣题的时候不止一次看到过这个PriorityQueue,他的优良特性可以帮助我们解决大量的题目。这篇文章从用法、原理、源码以及力扣实际题目的角度进行一个全面的分析。希望对你有帮助。

一、什么是优先级队列

1、概念

我们都知道队列,队列的核心思想就是先进先出,这个优先级队列有点不太一样。优先级队列中,数据按关键词有序排列,插入新数据的时候,会自动插入到合适的位置保证队列有序。(顺序有两种形式:升序或者是降序)

来一个标准点的定义:

PriorityQueue类在Java1.5中引入。PriorityQueue是基于优先堆的一个无界队列,这个优先队列中的元素可以默认自然排序或者通过提供的Comparator(比较器)在队列实例化的时排序。要求使用Java Comparable和Comparator接口给对象排序,并且在排序时会按照优先级处理其中的元素。

比如我们往队列里面插入132,插入2的时候,就会在内部调整为123(默认顺序是升序)。正是由于这个优良特性可以帮助我们实现一系列问题。我们先看一个例子,体会一下他的优点,然后再看一下为什么能够实现这样的功能。

我们看到就算是我们随意插入数据,但是输出的结果总是有序的,这样一来优先级队列就可以有了很多个使用场景。下面给出一道力扣题。体会一下他的优点。

2、案例演示特性

Leetcode215题:在未排序的数组中找到第 k个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

输入:3,2,3,1,2,4,5,5,6,k = 4。输出就是5,因此重复的并不考虑。我们一般情况下一般首先想到冒泡排序。每一次都冒出来一个最小的元素,这样冒K次,就是我们想要的结果。

其实冒泡排序还可以解决另外一个问题,那就是返回倒数第K大的元素,方法是每次冒出来一个最大的元素即可。

这样做很简单,但是需要我们自己手写冒泡排序,下面我们看使用优先级队列如何解决的。

就这几行代码就搞定了,是不是超级简单。为什么优先级队列能够实现呢?下面我们来分析一下他的数据结构:

3、数据结构

优先级队列底层的数据结构其实是一颗二叉堆,什么是二叉堆呢?我们来看看

在这里我们会发现以下特征:

(1)二叉堆是一个完全二叉树

(2)根节点总是大于左右子节点(大顶堆),或者是小于左右子节点(小顶堆)。

如果我们要插入一个节点怎么办呢?

自己使用画图工具画的,能看懂就行,不要在意那些细节兄弟。过程如下:

(1)找到待插入位置:满足完全二叉树的特点,依次插入

(2)插入之后判断是否满足二叉堆的性质,不满足那就调整

(3)1<==>6交换,发现不满足,1<==>4交换,满足即停止。

对于我们的优先级队列就是这样的一种数据结构,因此我们在插入的时候保证了数据的有序性。

OK。到这基本上我们能够体会到优先级队列的思想了。来一个小结:

优先级队列使用二叉堆的特点,可以使得插入的数据自动排序(升序或者是降序)。

现在我们知道了这些,还没讲源码。从源码的角度来体会一下:

二、源码分析(基于jdk1.8)

源码分析一般的顺序都是先类属性、构造方法、普通方法。在编译器中鼠标定位到这个PriorityQueue上,ctrl+鼠标左键就可以进入到这个集合的源码里面。

1、属性

2、构造方法

(1)默认构造方法:PriorityQueue()

使用默认的初始容量(11)创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。

(2)包含集合元素:PriorityQueue(Collection c)

创建包含指定 collection 中元素的 PriorityQueue。

(3)指定初始容量:PriorityQueue(int initialCapacity)

使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。

(4)指定初始容量和比较器:PriorityQueue(int initialCapacity, Comparator comparator)

使用指定的初始容量创建一个 PriorityQueue,并根据指定的比较器对元素进行排序。

(5)包含优先级元素:PriorityQueue(PriorityQueue c)

创建包含指定优先级队列元素的 PriorityQueue。

(6)包含set元素:PriorityQueue(SortedSet c)

创建包含指定有序 set 元素的 PriorityQueue。

3、普通方法

PriorityQueue中常用的方法很多。来看几个常用的。

(1)add:插入一个元素,不成功会抛出异常

public boolean add(E e) { return offer(e);}

我们看到add方法其实是通过调用offer方法实现的。我们直接看offer方法

(2)offer:插入一个元素,不能被立即执行的情况下会返回一个特殊的值(true 或者 false)

注意,优先级队列插入的元素不能为空,这一点在文章一开始提到过。步骤是这样的:

首先把modCount数量加1,如果容量不够把当前队列的尺寸加1,最后在i的位置上使用siftUp方法把e添加进来。此时真正插入的操作又落到了siftUp方法身上,我们接着看。

这里就是真正的插入操作了。一个正常的数据插入过程。没什么特别的。

(3)remove:删除一个元素,如果不成功会返回false。

这里会发现真正实现删除操作的是removeAt方法。我们跟进去看看

这个删除操作主要是两部分,if里面判断删除的是否是最后一个,否则的话就是用siftDown方法进行“向下沉”删除。不成功那就使用“向上浮”。

删除的时候同样需要进行判断比较器。

OK。删除操作就是这么多。基本思路是向上浮还是向下沉。

(4)poll:删除一个元素,并返回删除的元素

又回到了siftDown删除操作,就不赘述了。

(5)peek:查询队顶元素

实现原理很简单和上面的一样。

OK,源码就是这些。

三、优先级队列使用

上面已经介绍了原理和源码。而且给出了一个实际力扣案例。但是那属于算法,其实在真正工作领域也有不少的应用场景。

1、股票交易

我们的股票屏幕上总是给出最好或者是表现最差的那些股票。就可以基于优先级队列。方法其实是和找出前K个最大最小的元素方法类似。可以类比到股票中。

这只是给出了一个案例,你可以把股票交易的这样的使用场景类比到其他的场景中去。

2、会员项目

会员的优先级总是比普通会员高,因此我们就可以使用优先级队列保存会员的优先级。

这里只给出俩。其他的各位同僚自己体会吧,我自己曾经使用优先级队列来保存无人机的各种状态信息。所以也可以保存各种状态信息。

Java之PriorityQueue有序队列相关推荐

  1. java优先队列PriorityQueue修改队列内元素排序问题

    今天发现了新大陆.我以前一直以为,PriorityQueue队列是基于堆排序的不断更新排序的,没错,它是不断更新排序的.但是前提是要插入(删除)数据,如果仅仅是修改已经稳定队列的值或内容,而不进行插入 ...

  2. java 中PriorityQueue优先级队列使用方法

    1.前言 优先级队列是不同于先进先出队列的另一种队列.每次从队列中取出的是具有最高优先权的元素. PriorityQueue是从JDK1.5开始提供的新的数据结构接口. 如果想实现按照自己的意愿进行优 ...

  3. java中PriorityQueue优先级队列使用方法

    优先级队列是不同于先进先出队列的另一种队列.每次从队列中取出的是具有最高优先权的元素. PriorityQueue是从JDK1.5开始提供的新的数据结构接口. 如果不提供Comparator的话,优先 ...

  4. Java中的PriorityQueue优先级队列

    以前的博客中介绍过队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,此时出队列时需要优先级高的元素先出队列,这个时候传统的队列显然不能胜任,Java中有一个新的实现类继 ...

  5. 转:Java 7 种阻塞队列详解

    转自: Java 7 种阻塞队列详解 - 云+社区 - 腾讯云队列(Queue)是一种经常使用的集合.Queue 实际上是实现了一个先进先出(FIFO:First In First Out)的有序表. ...

  6. java 数据容器 有序_java容器-全览

    1.Collection全览-非线程安全的实现类 接口简介 Iterable:迭代器接口,用于遍历数据.foreach或者iterator. Collection:集合,java容器大部分集合的父类接 ...

  7. Java中的常用队列

    目录 一.队列的理解 二.Java中队列简述 2.1 Queue队列 2.2 双端队列 2.3 阻塞队列 2.4 非阻塞队列 三.各队列的区别与联系 一.队列的理解 队列是一种由数组和链表作为底层构造 ...

  8. JAVA中priorityqueue详解

    Java中PriorityQueue通过二叉小顶堆实现,可以用一棵完全二叉树表示.本文从Queue接口函数出发,结合生动的图解,深入浅出地分析PriorityQueue每个操作的具体过程和时间复杂度, ...

  9. java怎么遍历优先级队列_打印优先级队列的内容[java]

    如何使print_queue在Java中正常工作?这是我自己的队列实现. 使用Iterator()可以正常工作,除了它会以随机顺序打印数字. package data_structures_java ...

最新文章

  1. CVPR2020:三维点云无监督表示学习的全局局部双向推理
  2. 测序发展史,150年的风雨历程 (第二版)
  3. OSI七层网络模型TCP&UDP
  4. 云效助力新金融DevOps转型——南京银行实践之路
  5. IntelliJ IDEA设置JDK+java: -source 1.5中不支持diamond运算符
  6. 门面设计模式php,php设计模式-门面模式(Facade Pattern)
  7. 【APICloud系列|14】xcode下载地址
  8. sublime_text快捷键
  9. 新东方预计6个月亏损超8亿美元
  10. 如何使用Visual Studio无需成本即可实现连续集成
  11. 【Android】PA4D_CH6 使用Internat资源
  12. asp.net 运行原理
  13. Atitit DbServiceV4qb9 数据库查询类库v4 新特性
  14. Photoshop cc 2019安装与破解(附资源)
  15. php原创度检测工具,推荐一款不错的伪原创工具
  16. 磁环介绍与应用(转)
  17. leshan基于OMALightweight M2M(LwM2M)协议的Java实现(入门)
  18. nandwrite 参数
  19. 下载国外软件慢(例如:Python安装包)
  20. 第十六届D2大会(I)

热门文章

  1. poj 2723 2-SAT问题
  2. 091116 T 维护性
  3. Effective C# 原则38:使用和支持数据绑定(译)
  4. Spring自学日志02(对象的创建,依赖注入)
  5. 基于IDEA搭建JavaWeb入门项目结构(2021版)
  6. 单片机学c语言还是python好_单片机开发用哪种语言最好?
  7. python xampp mysql_php xampp mysql
  8. cat6 万兆_cat6 万兆
  9. 安装配置Exchange 问题集
  10. mysql中列的默认值