Java-数据结构-优先级队列(堆)-(二) (゚▽゚*)

文本目录:

❄️一、PriorityQueue的常用接口:

          ➷ 1、PriorityQueue的特性:

          ➷ 2、使用PriorityQueue的注意:

           ➷ 3、PriorityQueue的构造:

    ☞  1、无参数的构造方法:

     ☞  2、有参数的构造方法:

     ☞  3、带一个参数comparator的构造方法:

     ☞  4、用集合的构造方法:

           ➷ 4、PriorityQueue的插入和删除等方法:

    ☞  1、插入方法(offer(E e)):

    ☞  2、删除方法( poll() ) 和 查看优先级最高的( peek() ):

     ☞  3、获得有效元素的个数( size() ):

     ☞  4、判空( isEmpty() ):

 ❄️二、堆的应用:

          ➷ 1、PriorityQueue的实现:

          ➷ 2、堆排序:

          ➷ 3、Top-k问题:

  ❄️总结:


❄️一、PriorityQueue的常用接口:

          ➷ 1、PriorityQueue的特性:

        在 Java 集合中给我们提供了两种优先级队列:PriorityQueuePriorityBlockingQueue,它们肯定是有区别的,我们的 PriorityQueue  线程不安全PriorityBlockingQueue 线程安全的 ,我们这次呢主要介绍 PriorityQueue 

         我们还是请出我们的老朋友:

我们可以看到我们的  PriorityQueue  是实现 Queue 这个接口的。


          2、使用PriorityQueue的注意:

在我们使用  PriorityQueue  的时候我们要注意:


1、在我们使用  PriorityQueue  的时候我们需要导入包:

所以我们一定要导包。


 2、 PriorityQueue  中存放的数据必须是可以比较大小的,不能插入无法比较大小的对象,否则          会抛出 ClassCastException 异常。

     因为我们的优先级队列需要比较对象之后才进行存入,这时候我们比较时候要强转成 Comparable 这个,我们来看看这个的底层代码:

所以我们必须要存入可以比较的对象。 


3、我们不能插入 null 对象,否则会抛出 NullPointerException 这个异常。我们来看:

存入 null 就会抛出异常。 


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


5、插入和删除元素的时候的时间复杂度为O(logN)


6、 PriorityQueue 底层使用了堆的数据结构。


7、 PriorityQueue 默认情况下是 小堆 ------ 就是每次获得堆里最小的元素


           3、PriorityQueue的构造:

     我们的 优先级队列 的构造方法常见的有几种构造方法,我们来一一介绍来看,但是呢在我们介绍构造方法之前呢,我们来看看 优先级队列 的底层代码的一些代码:


    ☞  1无参数的构造方法:

我们来看看这个无参构造的底层代码:

public PriorityQueue(int initialCapacity) {this(initialCapacity, null);}

 这里呢我们调用的两个参数的构造方法,我们的 容量是默认的 11 个容量。


     ☞  2有参数的构造方法:

   我们同样先来看看底层的代码:

public PriorityQueue(int initialCapacity) {this(initialCapacity, null);}

这个呢就是创建一个 容量 为 initialCapacity 这个容量的 优先级队列

这里调用的同样是两个参数的构造方法。

这里要注意我们传入的参数不能 < 1。


     ☞  3带一个参数comparator的构造方法:

public PriorityQueue(Comparator<? super E> comparator) {this(DEFAULT_INITIAL_CAPACITY, comparator);}

这里同样是调用带两个参数的构造方法,我们传入的是一个比较器。容量 还是 11 这个默认参数


接下来我们来看看对于这几个构造方法所调用的 两个参数的构造方法是什么样的:

public PriorityQueue(int initialCapacity,Comparator<? super E> comparator) {if (initialCapacity < 1)throw new IllegalArgumentException();this.queue = new Object[initialCapacity];this.comparator = comparator;}

这个就是我们的底层代码。 

这里我们会直接把传入的参数直接给到 queue 这个的容量。之后把第二个参数给到我们的比较器 


     ☞  4用集合的构造方法:

我们还是先来看看底层代码:

public PriorityQueue(Collection<? extends E> c) {if (c instanceof SortedSet<?>) {SortedSet<? extends E> ss = (SortedSet<? extends E>) c;this.comparator = (Comparator<? super E>) ss.comparator();initElementsFromCollection(ss);}else if (c instanceof PriorityQueue<?>) {PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;this.comparator = (Comparator<? super E>) pq.comparator();initFromPriorityQueue(pq);}else {this.comparator = null;initFromCollection(c);}}

这里就是我们传入的集合会直接给到我们的数组中,来构造。 


           4、PriorityQueue的插入和删除等方法:

    这里呢我们只介绍一下关于插入方法的操作的流程,其余的呢,我们看一下演示结构,因为和我们上次博客实现的堆的方法原理是一样的。


    ☞  1、插入方法(offer(E e)):

     我们在上一个博客中已经介绍了堆的插入是如何实现的了,这里呢是类似的,我们在这里呢,我们直接来看看这个方法在Java中的执行流程图:  

    这里的 compareTo 这个方法默认的是 this.val - o.val 在上面就是 15 - 11,这样得到的就是小根堆如果我们想要实现大根堆,就把其变成 o.val - this.val 就可以了,我们来看看如何实现的: 


    ☞  2、删除方法( poll() ) 和 查看优先级最高的( peek() ):

我们来看看删除优先级最高的栈顶数据:


     ☞  3、获得有效元素的个数( size() )


     ☞  4、判空( isEmpty() )


 ❄️二、堆的应用:

          ➷ 1、PriorityQueue的实现:

     我们的 PriorityQueue 的底层使用的就是堆来实现的。


          ➷ 2、堆排序:

     堆排序就是使用堆的思想来实现排序,我们的排序有两种排序,升序 和 降序,我们分为来那个步骤来进行堆排序:

    1、建堆:

升序:建大堆。

降序:建小堆。

    2、利用堆删除的思想来进行排序:

      我们来使用堆排序 创建升序 来进行介绍如何建成堆排序。

      就是把一个 大根堆 的 第一个数据和最后一个数据进行交换,之后我们把交换完的第一个数据向下调整,再次变成大根堆但是要注意,我们交换完之后的位置不用再调整,我们这时候要使用 一个 临时变量进行记录 我们 向下调整 的判断是否结束的位置。我们来看看流程图:

这个理解之后呢,我们来看看这个对于 使用大根堆来实现升序 的代码要如何实现: 

 private void shiftDown(int parent,int usedSize) {int child = parent * 2 + 1;//parent根节点的左子树的节点while (child < usedSize) {//判断有没有右子树,如果有就把 child 设置为最大的值的下标if (child + 1 < usedSize && elem[child + 1] > elem[child]) {//右子树比左子树大把 child + 1,就是右子树child += 1;}if (elem[parent] < elem[child]) {//进行交换swap(elem,child,parent);//调整完,把 parent 和 child 进行调整位置parent = child;child = parent * 2 + 1;}else {//这是 parent下标的值大于child,跳出break;}}}private void swap(int[] elem,int i,int j) {int tmp = elem[i];elem[i] = elem[j];elem[j] = tmp;}
//这是我们的上次博客的代码。我们自实现的建立大根堆public void HeapSort() {//我们把第一个数据和最后一个数据进行交换//之后我们把 0 下标的值进行向下排序,这样之后我们会把大值放后面,小值放堆的前面int end = usedSize - 1;while (end > 0){swap(elem,0,end);shiftDown(0,end);end--;}}

     这就是我们的使用 大根堆进行排升序。对于 降序我们要使用建小堆来实现,我们和 用大堆实现升序就是思想是差不多的。


          ➷ 3、Top-k问题:

这个也是我们出现过的面试题。

                      ▶  Top-k的传送门:

                                       Top-k问题的最小k个数

     这个问题呢,就是求数据集合中前 k 个最大的元素或者是最小的元素,一般情况下呢都是数据比较多的情况下。

     我们对于这个问题呢,我们有三种不同的做法,假设我们有N个数据,我们来看:

1、直接排序,直接找到前 k 个。

2、建立一个我们有 N 个数据的堆,之后出前k个数据。

      就是如果求前 k 个最小的数据就是建小根堆。求前 k 个最大的数据就是建大根堆。

3、 比如我们求前k个最小的元素,我们执行:建立前k个大根堆,之后我们把N-K个元素和堆顶元         素进行比较,如果比堆顶的元素小,就把堆顶的数据删除,之后再把这个小的元素入堆

       对于求前k个最大的元素就是反之。(这个方法就是我们Top-k问题的最好的解决办法)

我们来看流程图:

    这样呢就是我们的最好的解决 Top-k 问题的思路了,之后理解这个之后呢,我们来看看我们的Top-k的代码如何编写:

class IntComp implements Comparator<Integer> {//这是把其变成大根堆@Overridepublic int compare(Integer o1, Integer o2) {return o2.compareTo(o1);}
}class Solution {public int[] smallestK(int[] arr, int k) {int[] ret = new int[k];if (arr == null || k == 0) {return ret;}//默认为小堆,我们传比较器PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(k,new IntComp());//把前k个元素放入到堆中for (int i = 0; i < k; i++) {priorityQueue.offer(arr[i]);}//之后从第 N-k 个数据开始比较知道比较结束//这里是求前k个最小的,所以把第 N-k 个数据和 堆顶进行比较,如果 N-k 小的话就是 删堆顶,入第N-k的元素堆for (int i = k; i < arr.length; i++) {int peekval = priorityQueue.peek();if (arr[i] < peekval) {priorityQueue.poll();priorityQueue.offer(arr[i]);}}//把堆里的元素放到数组中for (int i = 0; i < k; i++) {ret[i] = priorityQueue.poll();}return ret;}
}

    ※   注意:这里我们的 PriorityQueue 创建为什么要传参呢?因为我们默认的建堆方式是小根堆,我们是求前k个最小的元素,所以我们要建大根堆,所以我们要传比较器,使之变成大根堆。


  ❄️总结:

      OK,我们这次的博客就到这里就结束了,这里呢还是比较难理解的,所以我们要多进行练习一下,那么我们下次的博客呢,就开始接受我们的排序的问题了,这个排序还是很重要的,我们尽情期待吧!!!拜拜咯~~~

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

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

相关文章

Error when custom data is added to Azure OpenAI Service Deployment

题意&#xff1a;在向 Azure OpenAI 服务部署添加自定义数据时出现错误。 问题背景&#xff1a; I receive the following error when adding my custom data which is a .txt file (it doesnt matter whether I add it via Azure Cognitive Search, Azure Blob Storage, or F…

uniApp微信小程序扫描普通二维码跳转到小程序指定页面操作方法

这篇文章主要给大家介绍了关于微信小程序扫描普通二维码跳转到小程序指定页面操作的相关资料,需要的朋友可以参考下 1、首先我们需要在微信公众平台的开发管理——>开发设置&#xff0c;找到&#xff08;扫普通链接二维码打开小程序&#xff09;&#xff0c;点击添加,根据提…

C++ 9.20

练习&#xff1a;定义一个矩形类&#xff08;Rectangle&#xff09;&#xff0c;包含私有成员宽度&#xff08;width&#xff09;、高度&#xff08;height&#xff09; 包含公共成员函数&#xff1a; 初始化矩形&#xff08;init&#xff09; 设置宽度&#xff08;set_w&am…

给儿童掏耳朵用哪个好?儿童耳勺最建议买的五个牌子

儿童的耳朵清洁是家长最烦恼的事情之一&#xff0c;近年来传统耳勺出现的意外新闻颇多&#xff0c;棉签等工具的表面粗糙&#xff0c;稍不注意就会刮伤儿童脆弱的耳道肌肤&#xff0c;那么除了这些以外&#xff0c;给儿童掏耳朵用哪个好&#xff1f; 小编建议家长都入一个可视挖…

唤醒数据中台潜力,加速数据飞轮转动:数据驱动秘籍

在这个数据爆炸的时代&#xff0c;企业的数据资产正变得越来越重要。然而&#xff0c;收集和存储数据只是数据驱动旅程的第一步。如何唤醒这些沉睡的数据&#xff0c;真正让它们为业务服务&#xff1f; 这才是企业成功的关键。 数据中台曾被视为整合企业内外数据资源的利器&am…

javascript 3 个有序点的方向(Orientation of 3 ordered points)

给定三个点 p1、p2 和 p3&#xff0c;任务是确定这三个点的方向。 平面中有序三重点的方向可以是 逆时针 顺时针 共线 下图显示了 (a,b,c) 的不同可能方向 如果 (p1, p2, p3) 的方向共线&#xff0c;则 (p3, p2, p1) 的方向也共线。 如果 (p1, p2, p3) 的方向是顺时针&a…

Python GUI 编程:tkinter 初学者入门指南——窗口

目录&#xff1a; 创建窗口更改窗口标题更改窗口大小和位置窗口在屏幕上居中窗口设置的其他属性 Tkinter 是在 Python 中开发 GUI&#xff08;图形用户界面&#xff09;最常用的库。在本指南中&#xff0c;我们将引导您了解 Tkinter 的基本知识&#xff0c;学习如何使用 Tkinte…

Vue3:自定义事件实现组件通信

目录 一.性质 1.双向通信 2.灵活性 3.传参能力 4.声明机制 5.事件验证 6.修饰符支持 7.响应式更新 8.解耦组件 9.易于测试 10.性能优化 二.使用 1.父组件 2.子组件 三.代码 1.父组件代码 2.子组件代码 四.效果 在Vue3中&#xff0c;自定义事件是实现组件间通…

NLP(二)-文本表示

One-hot One-hot&#xff08;独热&#xff09;编码是一种最简单的文本表示方式。如果有一个大小为V的词表&#xff0c;对于第i个词$w_i$&#xff0c;可以用一个长度为V的向量来表示&#xff0c;其中第i个元素为1&#xff0c;其它为0.例如&#xff1a; 减肥&#xff1a;[1, 0,…

C++11之统一的列表初始化

一.{}初始化 在c98中&#xff0c;标准允许使用{}对数组或结构体元素进行统一的列表初始值设定&#xff1a; struct mess {int _x;string _str; }; int main() {//注意&#xff0c;使用new的一定是指针int* arr new int[4] {1, 2, 3, 4};//数组初始化int arr[] { 1,3,5,6 };…

深度学习激活函数

激活函数是神经网络模型重要的组成部分&#xff0c;本文作者Sukanya Bag从激活函数的数学原理出发&#xff0c;详解了十种激活函数的优缺点。 激活函数&#xff08;Activation Function&#xff09;是一种添加到人工神经网络中的函数&#xff0c;旨在帮助网络学习数据中的复杂模…

linux之nacos安装

1:下载nacos安装包 方式一、进入官网下载压缩包 官网地址 找到nacos-server-2.0.1.tar.gz 点击进行下载&#xff0c;下载完成后上传到服务器中。 方式二、使用wget命令下载 也有两种方式&#xff1a;第一种下载速度较慢 wget https://github.com/alibaba/nacos/releases/downl…

圆柱包围框-Bounding Cylinder-原理-代码实现

定义&#xff1a;使用一个圆柱体包围点云的所有点&#xff0c;通常用于长柱状物体。 优点&#xff1a;适合于柱状或长条形的点云。 缺点&#xff1a;计算较为复杂&#xff0c;尤其是确定圆柱体的轴线方向和半径。 找到圆柱尽量满足下面条件 找到能够完全包围3D物体的最小圆柱…

户外无线麦克风哪个牌子好,降噪麦克风哪个牌子好,领夹麦推荐

对于热爱记录与户外直播的自媒体人来说&#xff0c;一款高性能的无线领夹麦克风决定了音频的质量。市场上虽有品牌如大疆、罗德、西圣等凭借技术创新引领潮流&#xff0c;但同时也存在一些产品&#xff0c;因设计缺陷在运动时声音捕捉不稳定。作为运动爱好者与音频设备测评师&a…

网络资源模板--Android Studio 图书借阅App

目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 一、项目演示 网络资源模板--图书借阅App 二、项目测试环境 三、项目详情 首页 这段代码是一个 Android 应用的 MainActivity 类&#xff0c;功能简要总结如下&#xff1a; 1. **界面设置**&#xf…

数据结构不再难懂:带你轻松搞定图

数据结构入门学习&#xff08;全是干货&#xff09;——图 1 图 1.1 什么是图 图是一种用于表示多对多关系的数学模型。它由一组顶点和一组边构成&#xff0c;用于描述事物之间的复杂关联。 顶点&#xff1a;通常用 V (Vertex) 表示&#xff0c;代表事物或对象。边&#xf…

2024华为杯研赛E题保姆级教程思路分析

E题题目&#xff1a;高速公路应急车道紧急启用模型 今年的E题设计到图像/视频处理&#xff0c;实际上&#xff0c;E题的难度相对来说较低&#xff0c;大家不用畏惧视频的处理&#xff0c;被这个吓到。实际上&#xff0c;这个不难&#xff0c;解决了视频的处理问题&#xff0c;…

华为---代理ARP工作过程示例分析

目录 1. 示例场景 2. 基本配置 3. 配置代码 4. 测试验证 5. 抓包分析 5.1 在代理ARP环境下PC1和PC2通信分析 5.2 取消代理ARP环境下PC1和PC2通信分析 【1】取消R1路由器GE 0/0/1端口ARP代理 【2】取消R2路由器GE 0/0/1端口ARP代理 1. 示例场景 如上图所示&#xff0c;…

windows环境下配置MySQL主从启动失败 查看data文件夹中.err发现报错unknown variable ‘log‐bin=mysql‐bin‘

文章目录 问题解决方法 问题 今天在windows环境下配置MySQL主从同步&#xff0c;在修改my.ini文件后发现MySQL启动失败了 打开my.ini检查参数发现没有问题 [mysqld] #开启二进制日志&#xff0c;记录了所有更改数据库数据的SQL语句 log‐bin mysql‐bin #设置服务id&#x…

java重点学习-总结

十五 总结 https://kdocs.cn/l/crbMWc8xEZda &#xff08;总结全部的精华&#xff09; 1.面试准备 企业筛选简历规则简历编写注意事项(亮点)项目怎么找&#xff0c;学习到什么程度面试过程(表达结构、什么样的心态去找工作) 2.redis 缓存相关(缓存击穿、穿透、雪崩、缓存过期淘…