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
     **/
    @BeforeEach
    public 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
     **/
    @Test
    public 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) - 简书

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络(超详解!) 第一节计算机网络的性能指标

1.速率 比特&#xff08;bit&#xff09;是计算机中数据量的单位&#xff0c;也是信息论中使用的信息量的单位。 比特&#xff08;bit&#xff09;来源于 binary digit&#xff0c;意思是一个“二进制数字”&#xff0c;因此一个比特就是二进制数字中的一个 1 或 0。 速率是…

游戏软件的设计方法

游戏软件的设计是一个综合性的过程&#xff0c;涉及到多个方面&#xff0c;包括游戏概念、用户体验、技术实现等。以下是一般的游戏软件设计方法&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 明确游…

第二十章(多线程)

一.线程的简介 Windows操作系统是多任务操作系统&#xff0c;它以进程为单位。一个进程是一个包含有自身地址的程序&#xff0c;每个独立执行的程序都称为进程。也就是说每个正在执行的程序都是一个进程。系统可以分配给每一个进程有一段有限的使用CPU的时间&#xff08;也可以…

解释LED显示屏的裸眼3D特效原理

LED电子大屏幕的3D特效技术正在不断发展&#xff0c;而实现这一技术的原理主要包括分光、分色、分时和光栅等四种方法。这些原理都有各自的特点和应用场景&#xff0c;下面将对它们进行详细介绍。 1. 分光方法 分光方法是一种基于偏振光的3D显示技术。通过使用偏振滤镜或偏振片…

RISC-V_WCH系列微控器软件体系云端快速架构

1 概述 RISC-V内核的微控器MCU&#xff0c;正在以更高的性价比&#xff0c;快速取代传统的各类ARM系列微控制处理器。 针对常用的芯成RISC-V内核的泌恒WCH系列微控器MCU&#xff0c;推出了&#xff1a;RISC-V_WCH系列微控器软件体系快速架构云平台。只要以身份证号码做用户名…

好看的css样式案例网站

uiverse 网站地址&#xff1a;https://uiverse.io/all 比如说我们要这个案例的代码 点击get code就可以了 右侧有完整的示例代码。 svg波浪生成器 网站&#xff1a;https://getwaves.io/ 根据自己需求调节好之后点击这个下载按钮就可以了

如何把视频中不需要的人物去掉?

从视频中移除不想要的对象或区域&#xff0c;这项工作以前既繁琐复杂又很消耗时间。但使用“AI智能抠像”工具&#xff0c;只需几个简单的步骤&#xff0c;即可轻松移除视频中任何不想要的人物。 在制作视频的过程中&#xff0c;我们常常会遇到需要将视频中多余的人物去掉的情…

Python基础语法之学习type()函数

Python基础语法之学习type函数 一、代码二、效果 查看数据类型或者说查看变量存储的数据类型 一、代码 print(type("文本")) print(type(666)) print(type(3.14))二、效果 梦想是生活的指南针&#xff0c;坚持追逐梦想&#xff0c;终将抵达成功的彼岸。不要害怕失败…

递归实现全排列

思路: 对于给定的集合&#xff0c;选择一个元素作为当前位置的元素。将当前位置的元素与集合中其他位置的元素交换&#xff0c;依次产生新的排列。通过递归调用&#xff0c;将当前位置向后移动&#xff0c;继续生成新的排列。当当前位置达到集合的末尾时&#xff0c;表示生成了…

万字解析设计模式之观察者模式、中介者模式、访问者模式

一、观察者模式 1.1概述 观察者模式是一种行为型设计模式&#xff0c;它允许一个对象&#xff08;称为主题或可观察者&#xff09;在其状态发生改变时&#xff0c;通知它的所有依赖对象&#xff08;称为观察者&#xff09;并自动更新它们。这种模式提供了一种松耦合的方式&…

国产操作系统-银河麒麟V10

一、介绍 银河麒麟操作系统隶属于麒麟软件&#xff0c;麒麟软件是专业从事国产操作系统研发和产业化的企业&#xff0c;面向通用和专用领域打造安全创新的国产操作系统产品和相应解决方案&#xff0c;旗下拥有银河麒麟、中标麒麟、星光麒麟三大产品品牌。 麒麟软件官方网站地…

运行新vue3项目

一&#xff0c;下载node并安装 官网&#xff1a;https://nodejs.org/en/ 查看版本&#xff1a; node -v二&#xff0c;cd进入到vue3项目目录 cd D:\Program-space\HBuilderXProject\Vue3project三&#xff0c;npm install npm install四&#xff0c;查看安装 npm list五&a…

Django回顾2

目录 一.HTTP 1.URL介绍 2.格式&#xff1a; 3.补充&#xff1a; 二.web框架 1.什么是框架 2.什么是web框架 3.wsgi协议 基于wsgi协议的web服务器&#xff1a; 4.协议是怎么规定的 三.Django 1.MVC与MTV模型&#xff08;所有框架其实都遵循MVC架构&#xff09; 2.…

postgresql以及postgis安装

一、安装postgresql及postgis 1.下载postgresql https://www.enterprisedb.com/downloads/postgres-postgresql-downloads 我选择的版本为“postgresql-14.8-2-windows-x64.exe”。 2.以管理员模式运行安装程序 安装路径建议不要C盘&#xff0c;可能会由于权限问题导致目录…

机器学习实战第3天:手写数字识别

☁️主页 Nowl &#x1f525;专栏《机器学习实战》 《机器学习》 &#x1f4d1;君子坐而论道&#xff0c;少年起而行之 ​ 文章目录 一、任务描述 二、数据集描述 三、主要代码 &#xff08;1&#xff09;主要代码库的说明与导入方法 &#xff08;2&#xff09;数据预…

YOLOv8 onnx 文件推理多线程加速视频流

运行环境&#xff1a; MacOS&#xff1a;14.0Python 3.9Pytorch2.1onnx 运行时 模型文件&#xff1a; https://wwxd.lanzouu.com/iBqiA1g49pbc 密码:f40v 下载 best.apk后将后缀名修改为 onnx 即可模型在英伟达 T4GPU 使用 coco128 训练了 200 轮如遇下载不了可私信获取 代码…

【面试题】JavaScript高级循环方法

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;web前端面试题库 除了for循环♻️&#xff0c;for-of,for-each循环♻️也是一个不错的选择 先说for-of循环♻️ 认识for-of循环♻️…

【Flutter】graphic图表实现自定义tooltip

renderer graphic中tooltip的TooltipGuide类提供了renderer方法,接收三个参数Size类型,Offset类型,Map<int, Tuple>类型。可查到的文档是真的少,所以只能在源码中扒拉例子,做符合需求的修改。 官方github示例 官方示例 这个例子感觉像是tooltip和提供的那些属性的…

翻页电子书怎么制作?用简单的方法做出炫酷的效果!

现在很多公司都喜欢把一些内容做成电子书的形式&#xff0c;与传统的纸质文献相比呢&#xff0c;电子书具有存储量大、体积小、成本低、信息更新快、方便阅读等不可替代的优势&#xff0c;受到了越来越多人的喜爱。 如何制作翻页电子书呢&#xff1f;今天小编就专门给大家安利…

转录组学习第5弹-比对参考基因组

比对参考基因组 在构建文库的过程中需要将DNA片段化&#xff0c;因此测序得到的序列只是基因组的部分序列。为了确定测序reads在基因组上的位置&#xff0c;需要将reads比对回参考基因组上&#xff0c;这个步骤叫做比对&#xff0c;即文献中所提到的alignment或mapping。包括基…