- 当在算法题目中需要一直维护一个有顺序的数组时,这是就需要考虑小根堆和大根堆,不然时间复杂度就要达到O(n^2),而用小根堆或者大根堆进行存储时间复杂度只需要O(nlogn)。
- 并且Java中自带的一个接口优先队列PriorityQueue就是默认小根堆实现的,也可以根据需求生成大根堆。
1. PriorityQueue的使用
构造方法
这里只介绍三种常用的构造方法
PriorityQueue() | 不带参数,默认容量为11 |
---|---|
PriorityQueue(int initialCapacity) | 参数为初始容量,该初始容量不能小于1 |
PriorityQueue(Collection<? extends E> c) | 参数为一个集合 |
public class TestPriorityQueue {
public static void main(String[] args) {
PriorityQueue<Integer> p1 = new PriorityQueue<>(); //容量默认为11
PriorityQueue<Integer> p2 = new PriorityQueue<>(10); //参数为初始容量
List<Integer> list = new ArrayList<>();
list.add(0);
list.add(1);
list.add(2);
PriorityQueue<Integer> p3 = new PriorityQueue<>(list); //使用集合list作为参数构造优先
// 级队列
}
}
2. 常用方法
方法 说明
boolean offer(E e) | 插入元素e,返回是否插入成功,e为null,会抛异常 |
---|---|
E peek() | 获取堆(后面介绍堆)顶元素,如果队列为空,返回null |
E poll() | 删除堆顶元素并返回,如果队列为空,返回null |
int size() | 获取有效元素个数 |
void clear() | 清空队列 |
boolean isEmpty() | 判断队列是否为空 |
注意事项
PriorityQueue中存放的元素必须能比较大小,不能比较大小的对象不能插入,会抛出ClassCastException异常,这里特别注意自定义类型的数据,需要自己实现比较方法Comparator
例如:向优先级队列中插入两个自定义的学生类型的数据
- 不能插入null对象,否则会抛NullPointerException异常
- 内部可以自动扩容
- PriorityQueue 底层使用堆数据结构
- PriorityQueue 默认是小堆,如果想要创建大堆可以使用如下方式创建:
注意:o2-o1是创建大堆,o1-o2是创建小堆
PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
或者简单点直接:
PriorityQueue<Double> priorityQueue = new PriorityQueue<>(Collections.reverseOrder()); //默认小根堆,本题需要使用的是大根堆
说明:
- 如果容量小于64,按照oldCapacity的2倍扩容
- 如果容量大于等于64,按照oldCapacity的1.5倍扩容
- 如果容量超过MAX_ARRAY_SIZE,按照MAX_ARRAY_SIZE扩容