• PriorityQueue优先级队列


    前言

    优先级队列就是在堆的基础上进行改造,那么什么是堆,又什么是优先级队列呢?

    我们一起来看看吧!


    目录

    前言

    一、堆

    (一)堆的创建

    (二)堆的插入

    (三)堆的删除

    (四)模拟实现堆

    二、优先级队列

    (一)常用方法:

    (二)常考点

    结语


    一、堆

    堆就是堆中某个节点的值总是不大于或不小于其父节点的值。

    堆总是完全二叉树。

    Java底层的堆是顺序表,按照层序遍历的规则存储数据。

    堆分为小根堆和大根堆。

    1.小根堆(又名最小堆)

    就是堆中某个节点的值总是不小于其父节点的值。

    例如:

    2.大根堆(又名最大堆)

    就是堆中某个节点的值总是不大于其父节点的值。

     例如:

    以创建最小堆为例,给出的数据顺序是: 5、3、6、7、4、2.

    (一)堆的创建

    首先,根据给出的数据顺序,创建如下二叉树:

     从最后一个叶子节点开始调整(向上调整):

    时间复杂度是:O(n)

    (二)堆的插入

    假设要插入数据0:

    如果在插入数据时,堆满扩容;调整为向上调整。 

    时间复杂度是:O(log n)

    (三)堆的删除

    堆的删除一定删除的是堆顶元素。

    时间复杂度是:O(log n) 

    (四)模拟实现堆

    代码:

    1. import java.util.Arrays;
    2. import java.util.Comparator;
    3. class PriorityException extends RuntimeException{
    4. public PriorityException(String s){
    5. super(s);
    6. }
    7. }
    8. public class MyPriortyQueue implements Comparator {
    9. public int[] elem;
    10. public int usedSize;
    11. public MyPriortyQueue(int k) {
    12. elem = new int[k];
    13. }
    14. public MyPriortyQueue() {
    15. elem = new int[11];
    16. }
    17. @Override
    18. public int compare(Integer o1,Integer o2) {
    19. return o2.compareTo(o1);
    20. }
    21. /**
    22. * 建堆
    23. */
    24. public void createHeap(int[] array) {
    25. for(int i = 0; i < array.length; i++){
    26. elem[i] = array[i];
    27. usedSize++;
    28. }
    29. for(int i = (usedSize-1-1)/2; i >= 0; i--){
    30. shiftDown(i,usedSize-1);
    31. }
    32. }
    33. /**
    34. * 向下调整
    35. * @param root 是每棵子树的根节点的下标
    36. * @param len 是每棵子树调整结束的结束条件
    37. * 向下调整的时间复杂度:O(logn)
    38. */
    39. private void shiftDown(int root,int len) {
    40. int child = root*2+1;
    41. while(child < len){
    42. if(child+11])>0){
    43. child++;
    44. }
    45. if(compare(elem[root],elem[child])>0){
    46. int tmp = elem[root];
    47. elem[root] = elem[child];
    48. elem[child] = tmp;
    49. root = child;
    50. child = root*2+1;
    51. }else{
    52. break;
    53. }
    54. }
    55. }
    56. /**
    57. * 入队:仍然要保持是大根堆
    58. * @param val
    59. */
    60. public void push(int val) {
    61. if(isEmpty()){
    62. elem[0] = val;
    63. }else{
    64. elem[usedSize] = val;
    65. }
    66. usedSize++;
    67. shiftUp(usedSize-1);
    68. }
    69. /**
    70. * 向上调整
    71. * 默认除了需要调整的地方外,其余都是已经调整好了的
    72. */
    73. private void shiftUp(int child) {
    74. int parent = (child-1)/2;
    75. while(child > 0){
    76. if(compare(elem[parent],elem[child])>0){
    77. int tmp = elem[parent];
    78. elem[parent] = elem[child];
    79. elem[child] = tmp;
    80. child = parent;
    81. parent = (child-1)/2;
    82. }else{
    83. break;
    84. }
    85. }
    86. }
    87. public boolean isFull() {
    88. return usedSize == elem.length;
    89. }
    90. /**
    91. * 出队【删除】:每次删除的都是优先级高的元素
    92. * 仍然要保持是大根堆
    93. */
    94. public void pollHeap() throws PriorityException{
    95. if(isEmpty()){
    96. throw new PriorityException("pollHeap::队列无元素,删除失败");
    97. }
    98. elem[0] = elem[usedSize-1];
    99. usedSize--;
    100. shiftDown(0, usedSize-1);
    101. }
    102. public boolean isEmpty() {
    103. return usedSize == 0;
    104. }
    105. /**
    106. * 获取堆顶元素
    107. * @return
    108. */
    109. public int peekHeap() throws PriorityException{
    110. if(isEmpty()){
    111. throw new PriorityException("peekEmpty::队列无元素,获取失败");
    112. }
    113. return elem[0];
    114. }
    115. public static void main(String[] args) {
    116. MyPriortyQueue p = new MyPriortyQueue();
    117. int[] arr = {2,4,2,5,7,9,5,3};
    118. p.createHeap(arr);
    119. System.out.println("+=========创建一个堆========+");
    120. System.out.println(Arrays.toString(p.elem));
    121. p.push(10);
    122. System.out.println("+=========入一个值========+");
    123. System.out.println(Arrays.toString(p.elem));
    124. System.out.println("+=========输出堆顶========+");
    125. System.out.println(p.peekHeap());
    126. p.pollHeap();
    127. System.out.println("+=========删除堆顶=======+");
    128. System.out.println(Arrays.toString(p.elem));
    129. }
    130. }

    代码链接在GitHub:堆_练习模拟实现2 · Yjun6/DataStructrue@98faae5 (github.com)

    二、优先级队列

    PriorityQueue p = new PriorityQueue<>();

    (一)常用方法:

    boolean offer(E e)插入元素e,成功插入返回true;会自动扩容;如果e为空,会抛出异常
    E peek()获取优先级队列最高的元素;若队列为空,返回null
    E poll()移除优先级队列最高的元素;若队列为空,返回null
    int size()获取有效元素个数
    void clear()清空
    boolean isEmpty()判断是否为空

    关于创建优先级队列的方法:

    PriorityQueue()初始容量为11,默认无比较器
    PriorityQueue(int k)初始容量为k,k>0
    PriorityQueue(Collection c)用一个集合创建优先级队列

    优先级队列扩容说明:

    • 如果容量小于64,按照2倍扩容;
    • 如果容量大于等于64,按照1.5倍扩容;
    • 如果容量超过 MAX_ARRAY_SIZE,按照 MAX_ARRAY_SIZE 进行扩容。

    (二)常考点

    求前k个最大值、前k个最小值、第k个最大值、第k个最小值……

    面试题 17.14. 最小K个数 - 力扣(Leetcode)

    代码:

    1. class Solution {
    2. public int[] smallestK(int[] arr, int k) {
    3. if(arr == null || k == 0) return new int[k];
    4. Comp comp = new Comp();
    5. PriorityQueue priorityQueue = new PriorityQueue<>(comp);//求大根堆
    6. for(int i = 0; i < k; i++){
    7. priorityQueue.offer(arr[i]);
    8. }
    9. for(int i = k; i < arr.length; i++){
    10. if(arr[i] < priorityQueue.peek()){
    11. priorityQueue.poll();
    12. priorityQueue.offer(arr[i]);
    13. }
    14. }
    15. int[] str = new int[priorityQueue.size()];
    16. for(int i = 0; i < str.length; i++){
    17. str[i] = priorityQueue.poll();
    18. }
    19. return str;
    20. }
    21. }
    22. class Comp implements Comparator {
    23. @Override
    24. public int compare(Integer a, Integer b){
    25. return b.compareTo(a);
    26. }
    27. }

    结语

    小编能力有限,欢迎大家指出错误哦~

    这篇博客如果对你有帮助,给博主一个免费的点赞以示鼓励,欢迎各位🔎点赞👍评论收藏⭐,谢谢!!!

  • 相关阅读:
    【Go blog】Govulncheck v1.0.0 发布了!
    统信操作系统UOS上安装arm64版nginx
    redis 启动,关闭,查看状态
    Pytorch人体姿态骨架生成图像
    WRF4.2安装过程全记录
    一三六、从零到一实现自动化部署
    数据库防火墙技术展望【终章】
    c++——map和set的使用
    Zookeeper:Zookeeper的主从选举机制
    SQL知识大全(二):SQL的基础知识你都掌握了吗?
  • 原文地址:https://blog.csdn.net/m0_68700019/article/details/130910521