数据结构——优先级队列(PriorityQueue)
1.优先级队列
优先级队列可以看作队列的另一个版本,队列的返回元素是由是由插入顺序决定的,先进先出嘛,但是有时我们可能想要返回优先级较高的元素,比如最大值?这种场景下就由优先级队列登场。
优先级队列底层是由堆实现的,可以说理解了堆就理解了优先级队列。
2.堆的概念
堆可以看作一颗完全二叉树。它将数据以完全二叉树的顺序存储在数组中。堆又分为大根堆和小根堆,如果以完全二叉树的方式看待大小根堆。
大根堆就是对于这棵树及该树的每一棵子树都满足左右子树节点值小于根节点值。
小根堆就是对于这棵树及该树的每一棵子树都满足左右子树节点值大于根节点值。
具体图如下:
3.实现堆
堆是在一维数组中存储的,所以我们首先需要一个数组去存储我们堆中数据,然后我们还可以通过变量usedSize去表示当前堆中已有元素,具体代码如下:
public class MyHeap {private int [] elem;private int usedSize;public MyHeap(){//构造方法this.elem=new int[10];this.usedSize=0;}}
为方便演示,我们直接将参数数组中元素“复制”给堆中对应元素。具体代码如下:
public void initHeap(int [] array){for (int i = 0; i <array.length ; i++) {elem[i]=array[i];usedSize++;}}
//运行结果:MyHeap{elem=[10, 26, 98, 75, 15, 64, 85, 32, 12, 100], usedSize=10}
显然此时的堆只能看做为一个数组,其元素按照完全二叉树顺序排列如下图,既不是大根堆也不是小根堆。
我们要让它变成一个堆就必须对其元素调整,本文演示调整大根堆,那么,如何调整为大根堆?
我们的思路是:从最后一颗子树开始,一颗一颗调整直到根节点,那么对于每一棵树:我们先找到其左右节点的最大值,然后拿着这个最大值跟父节点比较,比父节点大就交换,不如它大就不动。如何找到最后一棵子树:最后一个叶节点对应的父节点,若父节点为p,子节点为i,则有i=2*p+1,p=(i-1)/2。叶子节点下标为usedSize-1,那么其父节点下标就是(usedSize-1-1)/2。所以我们可以写个for循环去遍历调整每棵二叉树。存在一种情况:我在交换父节点和子节点值之后的堆依然不符合大根堆规则,比如上图中75和26换,换完之后26显然比32小,所以还需要再进行交换,我们可以在一次交换过后让parent=child;child=2*parent+1
这样继续往下调整,但是我们也不能不限制的往下递归,所以需要一个结束条件,那就是child<usedSize
。具体代码如下:
for(int parent=(usedSize-2)/2;parent>=0;parent--){siftDown(usedSize,parent);}}//针对每一棵树的调整public void siftDown(int usedSize,int parent){int child=2*parent+1;while(child<usedSize){if(child+1<usedSize&&elem[child]<elem[child+1]){child++;}//child指向较大if(elem[child]>elem[parent]){int tmp=elem[child];elem[child]=elem[parent];elem[parent]=tmp;//调整值parent=child;child=2*parent+1;}else{break;}}
offer
作用:此方法用于向堆中添加元素
思路:首先判断堆满没,满了扩容,然后将元素插入到堆中末尾,随后向上调整,将该元素调整到合适位置。
由于usedSize我们可以在类中直接访问到,所以我们push之后的调整只传一个当前末尾节点的下标。然后根据此下标推算出其父节点。若父节点为p,子节点为i,则有i=2*p+1,p=(i-1)/2,如果插入节点大于其父节点就交换,然后child=parent,parent=(child-1)/2,注意此时parent是一级一级往上走的,所以这种调整方式也叫向上调整,同理,刚才那个parent一级一级往下走的就是向下调整。直到根节点遍历完毕或者该插入节点遇到了比它大的父节点就结束循环。具体代码如下:
public void push(int val){if(isFull()){elem=Arrays.copyOf(elem,2*elem.length);}elem[usedSize]=val;signUp(usedSize);//这里usedSize作为末尾节点下标传进去usedSize++;}private void signUp(int child) {int parent=(child-1)/2;while(parent>-1){if(elem[parent]<elem[child]){//交换int tmp=elem[parent];elem[parent]=elem[child];elem[child]=tmp;//调整child=parent;parent=(child-1)/2;}else {break;}}}private boolean isFull() {return usedSize==elem.length;}
2.2poll
作用:此方法用于拿出堆顶元素
思路:首先将堆顶元素与堆末元素交换,随后将usedSize减一,也就是逻辑上删除了它,等下次push就会覆盖它,但是交换后的堆一定不符合堆的性质,所以还需sfitDown将堆调整为正确的堆。具体代码如下:
public int poll(){int val=elem[0];int tmp=elem[0];elem[0]=elem[usedSize-1];elem[usedSize-1]=tmp;usedSize--;siftDown(usedSize,0);return val;}
3.优先级队列的基本特性
1.优先级队列中的元素必须是能比较大小的,不然会抛出ClassCastException异常。
2.优先级队列中不能插入null对象,不然会抛出NullPointerException。
3.优先级队列默认实现小根堆。
3.1如何改为大根堆
PriorityQueue<Integer> queue1=new PriorityQueue<>(Comparator.reverseOrder());
4.top-k问题
给定一组数据,求前K个最大/小的数据。
题目链接:https://leetcode.cn/problems/smallest-k-lcci
思路1:利用优先级队列的特性。看到那句 以任意顺序 我就知道这道题是为优先级队列量身定做的。具体代码实现:
public int[] smallestK(int[] arr, int k) {PriorityQueue<Integer> queue = new PriorityQueue<>();//非空校验int[] answer = new int[k];//根据题意,注意初始化大小一定要和返回数据数量一致if (arr == null || k <= 0) {int [] a=new int[0];return a;}for(int i=0;i<arr.length;i++){queue.offer(arr[i]);}for(int i=0;i<k;i++){answer[i]=queue.poll();}return answer;}
思路2:用堆排序。
如果求前K个最大值,我们就建小根堆。
如果求前K个最小值,我们就建大根堆。
本题求最小值,我们建大根堆,先把K个数据放到堆中,然后假定它们就是要返回的数据,因为我建的是大根堆,堆顶元素一定是目前堆中最小元素的“最大者”,可以把它理解为“门槛”,然后遍历剩余元素与这个“门槛”比较,如果比“门槛”也就是当前堆顶元素小那我就删除当前堆顶元素同时将这个元素插入进堆,然后继续遍历直到结束,最后返回堆中元素即可。
求最大值思路类似,我建小根堆这样堆顶元素就是当前堆中元素的最小值,如果你比堆顶元素大你就可以入堆,原来的元素被删除。(成王败寇这一块/.)
本题具体代码如下:
public int[] smallestK(int[] arr, int k) {if(arr==null||k<=0){int [] a=new int[0];return a;}PriorityQueue<Integer> queue=new PriorityQueue<>(Comparator.reverseOrder());for(int i=0;i<k;i++){queue.offer(arr[i]);}for(int i=k;i<arr.length;i++){//注意这里i从k开始遍历int peekVal=queue.peek();if(peekVal>arr[i]){queue.poll();queue.offer(arr[i]);}else{continue;}}int [] answer=new int[k];for(int i=0;i<k;i++){answer[i]=queue.poll();}return answer;}
That’s all.
相关文章:

数据结构——优先级队列(PriorityQueue)
1.优先级队列 优先级队列可以看作队列的另一个版本,队列的返回元素是由是由插入顺序决定的,先进先出嘛,但是有时我们可能想要返回优先级较高的元素,比如最大值?这种场景下就由优先级队列登场。 优先级队列底层是由堆实…...

代谢组数据分析(二十六):LC-MS/MS代谢组学和脂质组学数据的分析流程
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包依赖包安装包加载需要的R包数据下载以及转换mzML数据预处理代谢物注释LipidFinder过滤MultiABLER数据预处理过滤补缺失值对数变换数据标准化下游数据分析总结系统信息参考介…...
服务器上用脚本跑python深度学习的注意事项(ubantu系统)
bash: $\r: command not found 问题原因: 出现 bash: $\r: command not found 以及路径中出现 \r 通常是因为脚本文件是在Windows系统下编辑,然后在Linux(如Ubuntu)系统中运行。在Windows系统中,文本文件的换行符是 \…...

【ARM】【FPGA】【硬件开发】Chapter.1 AXI4总线协议
Chapter.1 AXI4总线协议 作者:齐花Guyc(CAUC) 一、总线介绍 AXI4总线 AXI4总线就像是SoC内部的“高速公路”,负责在不同硬件模块之间高效传输数据。 AXI4协议通过 5个独立通道 传输数据和控制信号,每个通道都有自己的信号线,互…...
青少年编程与数学 02-020 C#程序设计基础 10课题、桌面应用开发
青少年编程与数学 02-020 C#程序设计基础 10课题、桌面应用开发 一、桌面应用1. 主要特点2. 常见类型3. 优势4. 局限性 二、开发步骤1. 准备工作2. 创建项目3. 开发应用4. 运行调试5. 打包发布 三、Windows 窗体应用(一)定义(二)特…...

把 jar 打包成 exe
1. 把自己的项目先正常打成jar包 2. 使用exe4j工具将jar转换为exe 2.1 exe4j下载地址:https://www.ej-technologies.com/download/exe4j/files 2.2 下载完成之后激活 2.3 可以点击Change License,输入秘钥L-g782dn2d-1f1yqxx1rv1sqd 2.4 直接下一步…...

【目标检测】检测网络中neck的核心作用
1. neck最主要的作用就是特征融合,融合就是将具有不同大小感受野的特征图进行了耦合,从而增强了特征图的表达能力。 2. neck决定了head的数量,进而潜在决定了不同尺度样本如何分配到不同的head,这一点可以看做是将整个网络的多尺…...

【经验】Ubuntu中设置terminator的滚动行数、从Virtualbox复制到Windows时每行后多一空行
1、设置terminator的滚动行数 1.1 问题描述 在终端 terminator 中,调试程序时,只能查看有限行数的打印日志,大约是500行,怎么能增加行数 1.2 解决方法 1)安装terminator sudo apt install terminator和 terminato…...

使用微软最近开源的WSL在Windows上优雅的运行Linux
install wsl https://github.com/microsoft/WSL/releases/download/2.4.13/wsl.2.4.13.0.x64.msi install any distribution from microsoft store, such as kali-linux from Kali office website list of distribution PS C:\Users\50240> wsl -l -o 以下是可安装的有…...

HackMyVM-Teacher
信息搜集 主机发现 ┌──(kali㉿kali)-[~] └─$ nmap -sn 192.168.43.0/24 Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-01 01:02 EDT Nmap scan report for 192.168.43.1 Host is up (0.0084s latency). MAC Address: C6:45:66:05:91:88 (Unknow…...

BugKu Web渗透之矛盾
开启场景,打开网页。发现是一段php代码。 这段代码也很好理解,就是get方式传参num,如果num不是数字类型,那么输出num的值,并且num1时,输出flag的值。 首先看看is_numeric的意思。 开始我想到了使用科学技术…...
hot100 -- 4.子串系列
1.和为 K 的子数组 问题: 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 方法1:暴力枚举 # 方法1:暴力枚举(遍历子数组起点和终点&…...

Python实现P-PSO优化算法优化卷积神经网络CNN回归模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 随着人工智能和深度学习技术的快速发展,卷积神经网络(CNN)在图像分类、目标检测…...

ssm 学习笔记day03
环境搭建 spring配置数据库 1.在pom.xml安装相应的依赖 2.在properties里面配置数据库的相关信息,需要强调的一点是,一定不要在properties里面添加任何空格,否则就会像我一样搞了两小时,数据一直报错,然后发现是空格的…...

mkdir: cannot create directory ‘gitlab-stu’: No space left on device
Linux中创建目录时报错“mkdir: cannot create directory ‘gitlab-stu’: No space left on device”,磁盘空间不足。 使用df命令查看,发现 / 下面use%占满了: 查看inode使用情况: 可以看到docker的数据大部分存放在/var/lib/do…...
【前端面经】云智慧一面
写在前面:面经只是记录博主遇到的题目。每题的答案在编写文档的时候已经有问过deepseek,它只是一种比较普世的答案,要学得深入还是靠自己 Q:手撕代码,两个有序数组排序 A: function mysort(arr1, arr2) {…...

ESP8285乐鑫SOCwifi芯片32bit MCU和2.4 GHz Wi-Fi
简介 ESP8285 拥有完整的且⾃成体系的 Wi-Fi ⽹络功能,既能够独⽴应⽤,也可以作为从机搭载于其他主机 MCU 运⾏。当 ESP8285 独⽴应⽤时,能够直接从外接 flash 中启动。内置的⾼速缓冲存储器有利于提⾼系统性能,并且优化存储系统。…...

DL00916-基于深度学习的金枪鱼各类别目标检测含完整数据集
文末有获取方式 🚀 基于深度学习的金枪鱼目标检测——开创智能识别新领域! 在计算机视觉和深度学习的快速发展中,目标检测 技术已成为提升行业效率的核心利器。而对于海洋生物领域,尤其是金枪鱼的 目标检测,更是填补了…...

不可变集合类型转换异常
记录一个异常:class java.util.ImmutableCollections$ListN cannot be cast to class java.util.ArrayList (java.util.ImmutableCollections$ListN and java.util.ArrayList 文章目录 1、原因2、解决方式一3、解决方式二4、关于不可变集合的补充4.1 JDK8和9的对比4…...

【PyQt5】从零开始的PyQt5 - QLabel篇
从零开始的PyQt5 - QLabel篇 引言一、简述二、例程2.1 显示到QWidget窗口上2.2 重新设置Label大小和对齐方式2.3 添加内容,设置边框2.4 显示富文本 三、参考 引言 QLabel主要用于显示文本或图像,不提供用户交互功能。本文主要简述PyQt5中的QLabel以及展…...

多模态AI的企业应用场景:视觉+语言模型的商业价值挖掘
关键词:多模态AI | 视觉语言模型 | 企业应用 | 商业价值 | 人工智能 📚 文章目录 一、引言:多模态AI时代的到来二、多模态AI技术架构深度解析三、客服场景:智能化服务体验革命四、营销场景:精准投放与创意生成五、研…...

数据结构(7)树-二叉树-堆
一、树 1.树的概述 现实生活中可以说处处有树。 在计算机里,有一种数据结构就是像现实中的树一样,有根,有分支,有叶子;一大片树就叫做森林。 这些性质抽象到计算机里也叫树,大致长这个样子: …...
时序数据库IoTDB基于云原生的创新与实践
概述 Apache IoTDB 是一款独立自研的物联网时序数据库,作为 Apache 基金会的顶级项目,它融合了产学研的优势,拥有深厚的科研基底。IoTDB 采用了端边云协同的架构,专为物联网设计,致力于提供极致的性能。 数据模型 I…...

怎么快速判断一款MCU能否跑RTOS系统
最近有朋友在后台中私信我,说现在做项目的时候有时候总是会考虑要不要用RTOS,或者怎么考量什么时候该用RTOS比较好、 关于这个问题,我个人也是深有感触的,做开发这么久了,大大小小的产品都做过不少了。有用RTOS开发的…...

使用原生前端技术封装一个组件
封装导航栏 navbar-template.html <header><nav><ul><li><a href"index.html"><i class"fas fa-home"></i> 主页</a></li><li><a href"#"><i class"fas fa-theate…...

lesson04-简单回归案例实战(理论+代码)
理解线性回归及梯度下降优化 引言 在机器学习的基础课程中,我们经常遇到的一个重要概念就是线性回归。今天,我们将深入探讨这一主题,并通过具体的例子来了解如何利用梯度下降方法对模型进行优化。 线性回归简介 线性回归是一种统计方法&a…...

Java 面试中的数据库设计深度解析
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Java 面试中的数据库设计深度解析一、数据库…...

国内首发!具有GPU算力的AI扫描仪
奥普思凯重磅推出的具有GPU算力的扫描仪,是一款真正意义上的AI扫描仪,奥普思凯将嵌有OCR发票识别核心的高性能NPU算力棒与高速扫描仪相结合,实现软件硬件相结合,采用一体化外观设计,实现高速扫描、快速识别表单&#x…...

【开发技巧指北】IDEA修改默认绑定Maven的仓库地址
【开发技巧指北】IDEA修改默认绑定Maven的仓库地址 Microsoft Windows 11 家庭中文版 IIntelliJ IDEA 2025.1.1.1 默认的IDEA是有自己捆绑的Maven的(这是修改完毕的截图) 修改默认的Maven配置,路径是IDEA安装路径下的plugins D:\Softwares\I…...
数据存储与运算
计算机中的数据存储与运算 输出地址后看不懂格式,为什么? 第一节:进制转换基础 ✅ 常见进制: 十进制(Decimal):日常使用的 0~9二进制(Binary):计算机底层使…...