【Java数据结构】集合PriorityQueue及其背后的数据结构堆(优先级队列)(二)

简介: 【Java数据结构】集合PriorityQueue及其背后的数据结构堆(优先级队列)

堆的删除

注意:堆的删除一定删除的是堆顶元素。具体如下:

1. 将堆顶元素对堆中最后一个元素交换

2. 将堆中有效数据个数减少一个

3. 对堆顶元素进行向下调整

1. public void pollHeap() {
2. if(isEmpty()){
3. throw new RuntimeException();
4.         }
5. int temp=elem[0];
6.         elem[0]=elem[usedSize-1];
7.         elem[usedSize-1]=temp;
8.         usedSize--;
9. //保证依然是大根堆
10.         shiftDown(0,usedSize);
11. 
12.     }
13. 
14. public boolean isEmpty() {
15. return usedSize==0;
16.     }
17. 
18. /**
19.      *
20.      * @param root 是每棵子树的根节点的下标
21.      * @param len  是每棵子树调整结束的结束条件
22.      * 向下调整的时间复杂度:O(logn)
23.      */
24. private void shiftDown(int root,int len) {
25. 
26. int child=2*root+1;
27. 
28. while(child<len){
29. 
30. if(child+1<len&&elem[child]<elem[child+1]){
31. 
32.                 child++;
33.             }
34. 
35. if(elem[root]<elem[child]){
36. int temp=elem[root];
37.                 elem[root]=elem[child];
38.                 elem[child]=temp;
39.                 root=child;
40.                 child=2*root+1;
41. 
42.             }else {
43. break;
44.             }
45. 
46.         }
47. 
48. 
49.     }

用堆模拟实现优先级队列(完整代码)

1. import java.util.Arrays;
2. 
3. public class PriorityQueue {
4. public int[] elem;
5. public int usedSize;
6. 
7. public static final int DEFAULT_INIT_USESZIE=10;
8. public PriorityQueue() {
9.         elem=new int[DEFAULT_INIT_USESZIE];
10.     }
11. 
12. /**
13.      * 建堆的时间复杂度:O(n)
14.      *
15.      * @param array
16.      */
17. public void createHeap(int[] array) {
18. 
19. 
20. 
21. for(int i=0;i<array.length;i++){
22.             elem[i]=array[i];
23.             usedSize++;
24. if(isFull()){
25.                 elem= Arrays.copyOf(this.elem,2*this.elem.length);
26.             }
27.         }
28. for(int parent=(usedSize-1-1)/2;parent>=0;parent--){
29. 
30.             shiftDown(parent,usedSize);
31.         }
32. 
33.     }
34. 
35. /**
36.      *
37.      * @param root 是每棵子树的根节点的下标
38.      * @param len  是每棵子树调整结束的结束条件
39.      * 向下调整的时间复杂度:O(logn)
40.      */
41. private void shiftDown(int root,int len) {
42. 
43. int child=2*root+1;
44. 
45. while(child<len){
46. 
47. if(child+1<len&&elem[child]<elem[child+1]){
48. 
49.                 child++;
50.             }
51. 
52. if(elem[root]<elem[child]){
53. int temp=elem[root];
54.                 elem[root]=elem[child];
55.                 elem[child]=temp;
56.                 root=child;
57.                 child=2*root+1;
58. 
59.             }else {
60. break;
61.             }
62. 
63.         }
64. 
65. 
66.     }
67. 
68. 
69. /**
70.      * 入队:仍然要保持是大根堆
71.      * @param val
72.      */
73. public void push(int val) {
74. if(isFull()){
75.             elem= Arrays.copyOf(this.elem,2*this.elem.length);
76.         }
77.         elem[usedSize]=val;
78.         usedSize++;
79.         shiftUp(usedSize-1);
80. 
81.     }
82. 
83. private void shiftUp(int child) {
84. 
85. int parent=(child-1)/2;
86. 
87. while(child>0)
88. if(elem[child]>elem[parent]){
89. 
90. int temp=elem[child];
91.             elem[child]=elem[parent];
92.             elem[parent]=temp;
93.             child=parent;
94.             parent=(child-1)/2;
95.         }else{
96. break;
97.         }
98.     }
99. 
100. public boolean isFull() {
101. return usedSize== elem.length;
102.     }
103. 
104. /**
105.      * 出队【删除】:每次删除的都是优先级高的元素
106.      * 仍然要保持是大根堆
107.      */
108. public void pollHeap() {
109. if(isEmpty()){
110. throw new RuntimeException();
111.         }
112. int temp=elem[0];
113.         elem[0]=elem[usedSize-1];
114.         elem[usedSize-1]=temp;
115.         usedSize--;
116. //保证依然是大根堆
117.         shiftDown(0,usedSize);
118. 
119.     }
120. 
121. public boolean isEmpty() {
122. return usedSize==0;
123.     }
124. 
125. /**
126.      * 获取堆顶元素
127.      * @return
128.      */
129. public int peekHeap() {
130. if(isEmpty()){
131. return -1;
132.         }
133. return elem[0];
134.     }
135. }

常用接口介绍

Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,本文主要介绍PriorityQueue。

关于PriorityQueue的使用要注意:

1. 使用时必须导入PriorityQueue所在的包,即:

import java.util.PriorityQueue;

2. PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出

ClassCastException异常

3. 不能插入null对象,否则会抛出NullPointerException

4. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容

5. 插入和删除元素的时间复杂度为

6. PriorityQueue底层使用了堆数据结构, (注意:此处大家可以不用管什么是堆,后文中有介绍)

7. PriorityQueue默认情况下是小堆---即每次获取到的元素都是最小的元素

PriorityQueue常用接口介绍

构造器 功能介绍
PriorityQueue() 创建一个空的优先级队列,默认容量是11
PriorityQueue(int
initialCapacity)
创建一个初始容量为initialCapacity的优先级队列,注意:
initialCapacity不能小于1,否则会抛IllegalArgumentException异
PriorityQueue(Collection<?
extends E> c)
用一个集合来创建优先级队列

注意:默认情况下,PriorityQueue队列是小堆,如果需要大堆需要用户提供比较器

1. // 用户自己定义的比较器:直接实现Comparator接口,然后重写该接口中的compare方法即可
2. class IntCmp implements Comparator<Integer>{
3. @Override
4. public int compare(Integer o1, Integer o2) {
5. return o2-o1;
6. }
7. }
8. public class TestPriorityQueue {
9. public static void main(String[] args) {
10. PriorityQueue<Integer> p = new PriorityQueue<>(new IntCmp());

插入/删除/获取优先级最高的元素

函数名 功能介绍
boolean
offer(E e)
插入元素e,插入成功返回true,如果e对象为空,抛出NullPointerException异常,时
间复杂度 ,注意:空间不够时候会进行扩容
E peek() 获取优先级最高的元素,如果优先级队列为空,返回null
E poll() 移除优先级最高的元素并返回,如果优先级队列为空,返回null
int size() 获取有效元素的个数
void
clear()
清空
boolean
isEmpty()
检测优先级队列是否为空,空返回true
目录
打赏
0
0
0
0
2
分享
相关文章
|
4月前
|
散列表的数据结构以及对象在JVM堆中的存储过程
本文介绍了散列表的基本概念及其在JVM中的应用,详细讲解了散列表的结构、对象存储过程、Hashtable的扩容机制及与HashMap的区别。通过实例和图解,帮助读者理解散列表的工作原理和优化策略。
69 1
散列表的数据结构以及对象在JVM堆中的存储过程
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
135 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
8G的容器Java堆才4G怎么就OOM了?
本文记录最近一例Java应用OOM问题的排查过程,希望可以给遇到类似问题的同学提供参考。
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
108 5
Java对象一定分配在堆上吗?
本文探讨了Java对象的内存分配问题,重点介绍了JVM的逃逸分析技术及其优化策略。逃逸分析能判断对象是否会在作用域外被访问,从而决定对象是否需要分配到堆上。文章详细讲解了栈上分配、标量替换和同步消除三种优化策略,并通过示例代码说明了这些技术的应用场景。
Java对象一定分配在堆上吗?
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
169 16
Java 中的优先队列 PriorityQueue 详解
【10月更文挑战第22天】优先队列 PriorityQueue 是一种非常实用的数据结构,在许多场景中都能发挥重要作用。通过深入了解其特点和用法,我们可以更好地利用它来解决实际问题。
202 13
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
200 1
|
11天前
|
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
125 60
【Java并发】【线程池】带你从0-1入门线程池

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等