优先级队列
概念
队列是一种先进先出(FIFO)的数据结构。
但在有些情况下,我们进行操作的数据可能带有优先级,在出队列时可能需要优先级高的先出队列。因此,把具有返回优先级最高的对象和添加新对象操作的数据结构称为优先级队列(PriorityQueue)。
基本特性
- 使用时必须导入PriorityQueue所在的包:
import java.util.PriorityQueue;
- PriorityQueue中存放的元素必须是能够比较大小的,不能插入无法比较大小的对象,否则会抛异常。
- 不能插入null对象,否则会跑出空指针异常。
- 没有容量限制,可以插入任意多个元素,其内部可以自动进行扩容。
- 插入和删除元素的时间复杂度为O(logN)。
- PriorityQueue的底层结构使用了堆数据结构。(用数组存储数据
用树来组织数据) - 常见的优先级队列的构造方法:
代码示例:
public static void TestPriorityQueue(){
// 创建一个空的优先级队列,底层默认容量是11
PriorityQueue<Integer> q1 = new PriorityQueue<>();
// 创建一个空的优先级队列,底层的容量为initialCapacity
PriorityQueue<Integer> q2 = new PriorityQueue<>(100);
ArrayList<Integer> list = new ArrayList<>();
list.add(4);
list.add(3);
list.add(2);
list.add(1);
// 用ArrayList对象来构造一个优先级队列的对象
// q3中已经包含了三个元素
PriorityQueue<Integer> q3 = new PriorityQueue<>(list);
System.out.println(q3.size());
System.out.println(q3.peek());
}
默认情.况下,PriorityQueue队列底层默认容量是11.
- 优先级队列的扩容方式:
- 如果容量小于64时,按照oldCapacity*2+2的方式扩容。
- 如果容量大于等于64,按照oldCapacity*1.5的方式扩容。
private void grow(int minCapacity) {
int oldCapacity = queue.length;
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
(oldCapacity + 2) :
(oldCapacity >> 1));
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
queue = Arrays.copyOf(queue, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
- 常用方法:
- boolean offer(E e) :插入元素e,插入成功返回true,如果e对象为空,抛出异常,时间复杂度O(logN) ,注意:空间不够时候会进行扩容
- E peek() :获取优先级最高的元素,如果优先级队列为空,返回null
- E poll() :移除优先级最高的元素并返回,如果优先级队列为空,返回null
- int size() :获取有效元素的个数
- void clear(): 清空
- boolean isEmpty() :检测优先级队列是否为空,空返回true
- 优先级队列的应用:top-k问题
例如:
设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。
public int[] smallK(int[] arr,int k){
if(arr==null||k<=0){
return new int[0];
}
PriorityQueue<Integer> p = new PriorityQueue<>();
for(int i = 0;i < arr.length;i++){
p.offer(arr[i]);
}
int[] ret = new int[k];
for(int i = 0;i < k;i++){
ret[i] = p.poll();
}
return ret;
}