优先级队列

概念
队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列,该中场景下,使用队列显然不合适,比如:在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话。
在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。

接口

Java集合框架中提供了PriorityQueuePriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,关于PriorityQueue的使用要注意

  1. 使用时必须导入PriorityQueue所在的包,即:
import java.util.PriorityQueue;
  1. PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出ClassCastException异常,默认情况下:不论怎么调整,0号位置的元素始终是最小的
  2. 不能插入null对象,否则会抛出NullPointerException
  3. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容
  4. 插入和删除元素的时间复杂度为O(logN)
  5. PriorityQueue底层使用了堆数据结构,

PriorityQueue常用接口介绍:

  1. List itemPriorityQueue(), 构造一个空的优先级队列:空的优先级队列,但是底层已经有11个默认空间
PriorityQueue<Integer> p1=new PriorityQueue<>();
  1. PriorityQueue(int initialCapacity),创建一个初始容量为initialCapacity的优先级队列,
    注意:
    initialCapacity不能小于1,否则会抛IllegalArgumentException异常
    如果知道优先级队列中大概要放多少个元素,最好使用该种方式进行构造,不要使用空的构造方式构造,因为在插 入元素时,需要不断扩容而影响程序的效率
PriorityQueue<Integer> p2=new PriorityQueue<>(20);
  1. PriorityQueue(Collection<? extends E>c),用一个集合来创建优先级队列
List <Integer> s=new ArrayList<>();
        s.add(0);
        s.add(1);
        s.add(2);
        PriorityQueue<Integer> p3=new PriorityQueue<>(s);

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

函数名

功能介绍

boolean offer(E e)

插入元素e,插入成功返回true,如果e对象为空,抛出NullPointerException异常,时间复杂度O(logN),注意:空间不够时候会进行扩容

E peek()

获取优先级最高的元素,如果优先级队列为空,返回null

int size()

获取有效元素的个数

void clear()

清空

boolean isEmpty()

检测优先级队列是否为空,空返回true

经典的TOP-K

设计一个算法,找出数组中最小的个数。以任意顺序返回这K个数。
大家的方式:
1.sort排序:取前K个元素
2.二叉搜索树:按照中序遍历回收K个数据
3.优先级队列:peek,poll

class Solution {
    public int[] smallestK(int[] arr, int k) {
        // 参数检测
        if(null == arr || k <= 0)
            return new int[0];
        PriorityQueue<Integer> q = new PriorityQueue<>(arr.length);
        // 将数组中的元素依次放到堆中
        for(int i = 0; i < arr.length; ++i){
            q.offer(arr[i]);
        }
        // 将优先级队列的前k个元素放到数组中
        int[] ret = new int[k];
        for(int i = 0; i < k; ++i){
            ret[i] = q.poll();
        }
        return ret;
    }
}