Java数据结构之优先级队列(PriorityQueue)

1、概念

        队列:是一种FIFO(First-In-First-Out)先进先出的数据结构,对应于生活中的排队的场景,

排在前面的人总是先通过,依次进行。

        优先队列:是特殊的队列,从“优先”一词,可看出有“插队现象”(优先即比较大小)。比如送

进医院的患者,即便是按顺序到达的,生病更加严重的往往优先级也会更高。优先队列至少含有两

种操作的数据结构:

  • insert(插入),即将元素插入到优先队列中(入队);
  • 以及deleteMin(删除最小者),它的作用是找出、删除优先队列中的最小的元素(出队)。

PriorityQueue

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

上进行了一些调整。

2、堆

        堆严格意义上来说又叫二叉堆(Binary Heap),因为它的结构是一颗完全二叉树,堆一般分

为最大堆和最小堆。

堆的性质

  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 堆总是一棵完全二叉树。

堆的分类

大根堆父亲节点的值大于孩子节点的值
小根堆父亲节点的值小于孩子节点的值

数组表示堆

        由于是完全二叉树,节点的索引之间有着一定的关系,故我们可以使用数组来存储二叉堆,具体如下:

如果从索引为0开始存储,则父亲和孩子节点的索引关系如下:

3、PriorityQueue

构造方法

构造方法说明
PriorityQueue()不带参数,默认容量为11
PriorityQueue(int initialCapacity)参数为初始容量,该初始容量不能小于1
PriorityQueue(Collection<? extends E> c)参数为一个集合

常用方法  

方法说明
boolean offer(E e)插入元素e,返回是否插入成功,e为null,会抛异常
E peek()获取堆(后面介绍堆)顶元素,如果队列为空,返回null
E poll()删除堆顶元素并返回,如果队列为空,返回null
int size()获取有效元素个数
void clear()清空队列
boolean isEmpty()判断队列是否为空

注意:

  • add方法:等同offer。

4、Top-k问题

        即求数据中前k个最大或者最小元素,一般情况下数据量都会比较大。如果数据量大使用排序那种方法就不可取了,那么如何解决呢?

  1. 使用数据中前k个数据建堆
    1. 求前k个最大,建小堆
    2. 求前k个最小,建大堆
  2.  用剩余的元素依次与堆顶元素比较
    1. 求前k个最大,若比堆顶元素大,则替换小堆堆顶元素
    2. 求前k个最小,若比堆顶元素小,则替换大堆堆顶元素 

代码示例

问题:从文件中获取前10名的学生。

学生类

package com.ybw.interview.file.simple;import lombok.AllArgsConstructor;
import lombok.Getter;/*** 学生类** @author weixiansheng* @version V1.0* @className Student* @date 2023/11/28**/
@AllArgsConstructor
@Getter
public class Student {/*** 姓名** @author: weixiansheng* @date: 2023/11/28**/private String name;/*** 成绩** @author: weixiansheng* @date: 2023/11/28**/private Integer score;
}

获取top k数据 

package com.ybw.interview.file.simple;import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;import java.util.*;/*** 获取前10名学生** @author weixiansheng* @version V1.0* @className TopStudents* @date 2023/11/28**/
@Slf4j
public class TopStudents {public static final int TEN = 10;private Map<String, Integer> studentMap = new HashMap<>();/*** 初始化数据** @className TopStudents* @author weixiansheng* @date 2023/11/28* @version V1.0**/@BeforeEachpublic void init() {Random random = new Random();for (int i = 0; i < 100; i++) {studentMap.put("学生" + i, random.nextInt(100));}}/*** 打印前10名学生** @className TopStudents* @author weixiansheng* @date 2023/11/28* @version V1.0**/@Testpublic void printTopStudents() {//1、创建小顶堆PriorityQueue<Student> topStudents = new PriorityQueue<>(10, Comparator.comparingInt(Student::getScore));//2、构建前10名学生buildTopStudents(topStudents);//3、打印前10名学生for (int i = 0; i < TEN; i++) {Student student = topStudents.poll();log.info("{}:{}", student.getName(), student.getScore());}}/*** 构建前10名学生** @param topStudents* @methodName: buildTopStudents* @return: void* @author: weixiansheng* @date: 2023/11/28**/private void buildTopStudents(PriorityQueue<Student> topStudents) {studentMap.forEach((name, score) -> {if (topStudents.size() < TEN) {topStudents.add(new Student(name, score));} else if (score > topStudents.peek().getScore()) {topStudents.poll();topStudents.add(new Student(name, score));}});}
}

打印日志:

[INFO ] 2023-11-28 15:41:44.519 [main] c.y.i.file.simple.TopStudents - 学生59:92
[INFO ] 2023-11-28 15:41:44.520 [main] c.y.i.file.simple.TopStudents - 学生46:92
[INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生28:93
[INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生80:94
[INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生21:94
[INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生71:95
[INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生75:95
[INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生87:95
[INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生82:97
[INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生76:98

参考文章:

Java数据结构之优先级队列(PriorityQueue)用法详解_java_脚本之家 

优先队列(PriorityQueue) - 简书

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 实现微信退款及对帐

目录 需求 基础准备 关键代码 操作界面 ​编辑 退款订单类及方法 退款功能实现 对帐 支付商家后台相关要点 实时交易帐单查询 精确交易帐单查询 小结 需求 在招聘报名系统里&#xff0c;考务费支付是其中一个环节&#xff0c;支付方式很多种&#xff0c;比如银联、…

GitHub----使用记录

一、上传文件到仓库 1、首先新建一个github仓库 然后先记住这一句指令 2、下载git工具 https://git-scm.com/downloads 下载工具安装不用运行 3、使用git工具上传文件并推送 找到你想上传的文件的位置&#xff0c;右击git Bush here git init &#xff1a;初始化这个仓…

【项目实战】SpringBoot连接openGauss

一&#xff1a;Docker安装openGauss 1.下载openGauss 安装好Docker好以后&#xff0c;执行如下命令下载openGauss3.0镜像。docker pull enmotech/opengauss:3.0.0 2.运行openGauss 执行如下命令docker run -itd --name opengauss \ --restartalways \ --privilegedtrue \ …

OpenAi Q* (Q Star)项目入门介绍

为初学者解释 Open Ai 的 Q*(Q Star) Q* 的两个可能来源。 1)Q 可能是指 "Q-learning",这是一种用于强化学习的机器学习算法。 Q 名称的由来*:把 "Q*"想象成超级智能机器人的昵称。 Q 的意思是这个机器人非常善于做决定。 它从经验中学习,就像你从玩…

什么是数据填报?

数据填报是报表用以满足用户提出的灵活报送数据的需求&#xff0c;能快速开发各类数据采集系统的专业功能。多源填报模型&#xff0c;可实现数据的多源抽取与多源回填&#xff0c;在同一张填报表上实现数据提交至多个不同的数据表、数据库。 随着业务快速变化和扩大&#xff0c…

邮件群发:避免垃圾邮箱,提升营销效果

群发邮件为什么会进入垃圾邮箱呢&#xff1f;常见的原因有&#xff1a;邮件内容出现问题、域名和IP的信誉度不高、退订数或投诉过多等原因。所以&#xff0c;营销人员在做EDM的时候&#xff0c;应该把握方式技巧&#xff0c;才能获取良好的营销效果&#xff0c;避免邮件成为垃圾…

特征可视化,代码详解

输入 输出 代码 import os import torch import torchvision as tv import torchvision.transforms as transforms import torch.nn as nn import torch.optim as optim import argparse import skimage.data import skimage.io import skimage.transform import numpy as np…

15:00面试,15:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

C++值常用集合算法

C值常用集合算法 set_intersection #include<iostream> using namespace std; #include<vector> #include<numeric> #include<algorithm>class MyPrint { public:void operator()(int val){cout << val<<" ";} };void test() {v…

EC 404 information economics

EC 404 information economics WeChat: zh6-86

【Cmake】Cmake基础学习

CMake学习 一、基础学习 1. 利用Cmake进行单个源代码构建可执行文件 (1)基础命令 最基本的 CMake项目是由单个源代码文件构建的可执行文件。对于这样的简单项目,只需要一个包含三个命令的 CMakeLists.txt 文件。 注意: 虽然 CMake 支持大写、小写和混合大小写命令,但是…

个人投资白银收益怎么样?

个人投资白银是可以带来丰厚的收益&#xff0c;但收益的具体情况取决于多种因素。以下是一些明确的答案和举例&#xff0c;帮助投资者更好地理解个人投资白银的收益情况。 白银市场的价格波动是决定投资收益的主要因素之一&#xff0c;白银价格受全球经济形势、地缘局势风险、…