优先级队列

目录

优先级队列(PriorityQueue)

概念

优先级队列的特性

使用优先级队列时需注意: 

优先级队列的构造

优先级队列的操作实现 


 

优先级队列(PriorityQueue)

概念

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

优先级队列的特性

Java 集合框架中提供了 PriorityQueue PriorityBlockingQueue 两种类型的优先级队列, PriorityQueue 是线 程不安全的, PriorityBlockingQueue 是线程安全的

使用优先级队列时需注意: 

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

import java.util.PriorityQueue;
2. PriorityQueue 中放置的 元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出
ClassCastException 异常
3. 不能 插入 null 对象,否则会抛出 NullPointerException
4. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容
5. 插入和删除元素的时间复杂度为O(log₂N)
6. PriorityQueue 底层使用了堆数据结构
7. PriorityQueue 默认情况下是小堆 --- 即每次获取到的元素都是最小的元素  

优先级队列的构造

此处只是列出了PriorityQueue中常见的几种构造方式

构造器功能介绍
PriorityQueue()
创建一个空的优先级队列,默认容量是11
PriorityQueue(int
initialCapacity)
创建一个初始容量为 initialCapacity 的优先级队列,注意:initialCapacity不能小于 1 ,否则会抛Ill egalArgumentException 异常
PriorityQueue(Collection<?
extends E> c)
用一个集合来创建优先级队列
static void TestPriorityQueue(){
       // 创建一个空的优先级队列,底层默认容量是11
       PriorityQueue<Integer> p1 = new PriorityQueue<>();
       // 创建一个空的优先级队列,底层的容量为initialCapacity
       PriorityQueue<Integer> p2 = new PriorityQueue<>(100);
       List<Integer> list = new ArrayList<>();
       list.add(4);
       list.add(3);
       list.add(2);
       list.add(1);
       // 用ArrayList对象来构造一个优先级队列的对象
       PriorityQueue<Integer> p3 = new PriorityQueue<>(list);
       System.out.println(p3.size());//size = 4
       System.out.println(p3.peek());//peek = 1
}
注意:默认情况下, PriorityQueue 队列是小堆,如果需要大堆需要用户提供比较器
// 用户自己定义的比较器:直接实现Comparator接口,然后重写该接口中的compare方法即可
class IntCmp implements Comparator<Integer>{
    public int compare(Integer o1, Integer o2) {
    return o2-o1;
    }
}
public class TestPriorityQueue {
    public static void main(String[] args) {
    PriorityQueue<Integer> p = new PriorityQueue<>(new IntCmp());
    p.offer(4);
    p.offer(3);
    p.offer(2);
    p.offer(1);
    p.offer(5);
    System.out.println(p.peek());//peek = 5
    }
}

此时创建出来的就是大堆。

优先级队列的操作实现 

优先级队列(priority queue)是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有(1)查找(2)插入一个新元素(3)删除  一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。

函数名功能介绍
boolean offer(E e)
插入元素 e ,插入成功返回 true ,如果 e 对象为空,抛出 NullPointerException 异常,时间复杂度O(log₂N),注意:空间不够时候会进行扩容
E peek()
获取优先级最高的元素,如果优先级队列为空,返回 null
E poll()
移除优先级最高的元素并返回,如果优先级队列为空,返回 null
int size()
获取有效元素的个数
void clear()
清空
boolean isEmpty()
检测优先级队列是否为空,如果空返回 true
static void TestPriorityQueue2(){
    int[] arr = {4,1,9,2,8,0,7,3,6,5};
    PriorityQueue<Integer> q = new PriorityQueue<>(arr.length);
    for (int i = 0; i < arr.length; i++) {
        q.offer(i);
    }
    System.out.println(q.size()); // 打印优先级队列中有效元素个数
    System.out.println(q.peek()); // 获取优先级最高的元素
    // 从优先级队列中删除两个元素,再次获取优先级最高的元素
    q.poll();
    q.poll();
    System.out.println(q.size()); // 打印优先级队列中有效元素个数
    System.out.println(q.peek()); // 获取优先级最高的元素
    q.offer(0);
    System.out.println(q.peek()); // 获取优先级最高的元素
    // 将优先级队列中的有效元素删除掉,检测其是否为空
    q.clear();
    if(q.isEmpty()){
       System.out.println("优先级队列已经为空");
    }else{
       System.out.println("优先级队列不为空");
    }
}
以下是 JDK 1.8中, 优先级队列的扩容说明:
  • 如果容量小于64时,是按照oldCapacity2倍方式扩容的
  • 如果容量大于等于64时,是按照oldCapacity1.5倍方式扩容的
  • 如果容量超过MAX_ARRAY_SIZE,按照MAX_ARRAY_SIZE来进行扩容
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

private void grow(int minCapacity) {
   int oldCapacity = queue.length;
   // Double size if small; else grow by 50%
   int newCapacity = oldCapacity + ((oldCapacity < 64) ? (oldCapacity + 2) : (oldCapacity >> 1));
   // overflow-conscious code
   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; 
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值