PriorityQueue的底层是堆,堆的底层是数组。
一、什么是堆
堆就是一颗顺序存储的完全二叉树,底层是一个数组。
- 堆逻辑上是一颗完全二叉树。
- 堆物理上是存储在数组中的。
画个图就好理解了:

二、什么是最大堆、最小堆
- 最大堆:每个节点都大于等于它的两个子节点,排序最前面的元素一定是所有元素中最大的元素。
- 最小堆:每个节点都小于等于它的子节点,排序在最前面的元素一定是所有元素中最小的元素。
如下图所示:

三、使用注意点
- 必须导入PriorityQueue所在的包。
- 队列中放置的元素必须要能够比较大小(只有实现了Comparable和Comparator接口的类才能比较大小),不能插入无法比较大小的对象。
- 不能插入null对象。
- 没有容量限制,可以插入任意多个元素,其内部可以自动扩容。
PS:对于第二点中,如果传入的是链表中的节点对象,是无法直接比较大小,只能用链表对应的值才能比较大小。
//1. 最小堆用lamda表达式写,注意是a.val-b.val,而不是a-b
PriorityQueue<ListNode> pq = new PriorityQueue<>((a,b)->(a.val-b.val));
//2.最大堆用lamda表达式写,注意是b.val-a.val,而不是b-a
PriorityQueue<ListNode> pq = new PriorityQueue<>((a,b)->(b.val-a.val));
四、JAVA中使用优先队列,实现最大/小堆
先记住一句口诀:默认使用最小堆,最大堆后面减前面!!!
先来看最小堆
public class SmallHeap {
public static void main(String[] args) {
int[] a = {2,17,4,12,8,21,15,33};
//1,默认实现的是最小堆,元素按照natural ordering排序(自然排序,例如,数字的从小到大)
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
for (int i : a) {
pq.offer(i);
}
while(!pq.isEmpty()) {
System.out.print(pq);
}
//输出(升序):[2, 8, 4, 17, 12, 21, 15, 33]
}
}
再来看看最大堆
public class Test {
public static void main(String[] args) {
int[] a = {2,17,4,12,8,21,15,33};
//1.可以直接使用lamda表达式实现最大堆
PriorityQueue<Integer> pq =new PriorityQueue<>((a, b) -> b - a);
//2,通过比较器排序,实现最大堆
/* PriorityQueue<Integer> pq = new PriorityQueue<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
// 以下是对比较器升序、降序的理解.
// (1) 写成return a.compareTo(b) 或者 return a-b表示升序(最小堆)
// (2) 写成return b.compareTo(a) 或者 return b-a表示降序(最大堆)
return b.compareTo(a);
}
}) ;
*/
for (int i : a) {
pq.offer(i);
}
while(!pq.isEmpty()) {
System.out.print(pq);
}
//输出(降序):[33, 21, 17, 12, 8, 4, 15, 2]
}
}
最后补充一些PriorityQueue类常用的函数:

本文介绍了PriorityQueue在Java中的应用,包括堆的数据结构原理、最大堆和最小堆的概念、使用时的注意点,以及如何通过lambda表达式和Comparator实现最大/小堆操作。实例演示了如何构造最小堆和最大堆并输出结果。

6019

被折叠的 条评论
为什么被折叠?



