当前位置:   article > 正文

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

java 优先队列

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名的学生。

学生类

  1. package com.ybw.interview.file.simple;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Getter;
  4. /**
  5. * 学生类
  6. *
  7. * @author weixiansheng
  8. * @version V1.0
  9. * @className Student
  10. * @date 2023/11/28
  11. **/
  12. @AllArgsConstructor
  13. @Getter
  14. public class Student {
  15. /**
  16. * 姓名
  17. *
  18. * @author: weixiansheng
  19. * @date: 2023/11/28
  20. **/
  21. private String name;
  22. /**
  23. * 成绩
  24. *
  25. * @author: weixiansheng
  26. * @date: 2023/11/28
  27. **/
  28. private Integer score;
  29. }

获取top k数据 

  1. package com.ybw.interview.file.simple;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.junit.jupiter.api.BeforeEach;
  4. import org.junit.jupiter.api.Test;
  5. import java.util.*;
  6. /**
  7. * 获取前10名学生
  8. *
  9. * @author weixiansheng
  10. * @version V1.0
  11. * @className TopStudents
  12. * @date 2023/11/28
  13. **/
  14. @Slf4j
  15. public class TopStudents {
  16. public static final int TEN = 10;
  17. private Map<String, Integer> studentMap = new HashMap<>();
  18. /**
  19. * 初始化数据
  20. *
  21. * @className TopStudents
  22. * @author weixiansheng
  23. * @date 2023/11/28
  24. * @version V1.0
  25. **/
  26. @BeforeEach
  27. public void init() {
  28. Random random = new Random();
  29. for (int i = 0; i < 100; i++) {
  30. studentMap.put("学生" + i, random.nextInt(100));
  31. }
  32. }
  33. /**
  34. * 打印前10名学生
  35. *
  36. * @className TopStudents
  37. * @author weixiansheng
  38. * @date 2023/11/28
  39. * @version V1.0
  40. **/
  41. @Test
  42. public void printTopStudents() {
  43. //1、创建小顶堆
  44. PriorityQueue<Student> topStudents = new PriorityQueue<>(
  45. 10, Comparator.comparingInt(Student::getScore)
  46. );
  47. //2、构建前10名学生
  48. buildTopStudents(topStudents);
  49. //3、打印前10名学生
  50. for (int i = 0; i < TEN; i++) {
  51. Student student = topStudents.poll();
  52. log.info("{}:{}", student.getName(), student.getScore());
  53. }
  54. }
  55. /**
  56. * 构建前10名学生
  57. *
  58. * @param topStudents
  59. * @methodName: buildTopStudents
  60. * @return: void
  61. * @author: weixiansheng
  62. * @date: 2023/11/28
  63. **/
  64. private void buildTopStudents(PriorityQueue<Student> topStudents) {
  65. studentMap.forEach((name, score) -> {
  66. if (topStudents.size() < TEN) {
  67. topStudents.add(new Student(name, score));
  68. } else if (score > topStudents.peek().getScore()) {
  69. topStudents.poll();
  70. topStudents.add(new Student(name, score));
  71. }
  72. });
  73. }
  74. }

打印日志:

  1. [INFO ] 2023-11-28 15:41:44.519 [main] c.y.i.file.simple.TopStudents - 学生59:92
  2. [INFO ] 2023-11-28 15:41:44.520 [main] c.y.i.file.simple.TopStudents - 学生46:92
  3. [INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生28:93
  4. [INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生80:94
  5. [INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生21:94
  6. [INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生71:95
  7. [INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生75:95
  8. [INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生87:95
  9. [INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生82:97
  10. [INFO ] 2023-11-28 15:41:44.521 [main] c.y.i.file.simple.TopStudents - 学生76:98

参考文章:

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

优先队列(PriorityQueue) - 简书

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/791695
推荐阅读
相关标签
  

闽ICP备14008679号