当前位置: 首页 > news >正文

java数据结构_优先级队列(堆)_6.2

3. 常用接口

3.1 PriorityQueue的特性

Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列PriorityQueue的线性不安全的,PriorityBlockingQueue是线程安全的,这里主要介绍PriorityQueueu。

关于PriorityQueue的使用要注意:

  1. 使用时需要导包,即  import java.util.PriorityQueue;
  2. PriorityQueue中放置的元素必须要能够比较大小,不能擦汗如无法比较大小的对象,否则会抛出ClassCastException异常,如下图
  3. 不能插入null对象,否则会抛出NullPointerException
  4. “没有容量限制”,可以插入任意多个元素,因为其内部利用Array.copyOf可以自动扩容
  5. 插入和删除元素的时间复杂度为O(log2N)
  6. 底层使用的是堆结构
  7. 其默认情况下是小根堆 --> 即每次获得到的元素第是最小的元素

3.2 PriorityQueue常用接口介绍

1.优先级队列的构造

在IDEA中的PriorityQueue的Structure中可以看到PriorityQueue有多种构造方法

下面为相关源码实现,此处仅作列举,后面会讲解

总结:

使用:

默认情况下,PriorityQueue队列是小根堆,如果需要是大根堆,需要用户提供比较器:

此处先不作介绍,铺垫一下

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

就是方法的使用,很简单

补充:JDK1.8中,PriorityQueue的扩容方式:

4. Top - k问题

TOP-K问题:即求数据集合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。

做法1:把数组进行排序 排序之后 取出前K个最大的或者最小的。但是,当数据量非常大的时候,无法再内存中进行排序。

做法2:把所有数据都放入优先级队列中,前K个最大值,就用大根堆,前K个最小值,就用小根堆,出队K次即可。但是,仍然是上面的问题,如果数据量非常大的时候,是无法把所有的数据都放入优先级队列的。

代码如下:

public int[] smallestK(int[] array, int k) {
    int[] ret = new int[k];
    if(array == null || k <= 0) {
        return ret;
    }

    PriorityQueue<Integer> p = new PriorityQueue<>(array.length);

    for(int i = 0; i < array.length; i++) {
        p.offer(array[i]);
    }

    for(int i = 0; i < k; i++) {
        ret[i] = p.poll();
    }
    return ret;
}

且上面两种方法还有一点不好的地方是:效率十分低下。

建议的做法:

如果求前K个最小的数据,可以创建一个容量为K的大根堆,先添加K个元素进入这个大根堆中,然后将剩下的元素,每次都和堆顶元素进行比较如果比堆顶小如果该元素比堆顶元素小,又因为是大根堆,则堆顶元素一定不是前K个最小的元素之一),那么堆进行出队操作然后把当前数组中的元素存放到大小为K的大根堆中

如下图:求前3个最小的元素,先创建一个容量为3的大根堆

然后再将剩余的元素9,2逐个和堆顶元素进行比较,如果小于该堆顶元素,就进行出队操作,然后把当前数组中的元素存放到大小为K的大根堆中

最终得到的容量为K的大根堆,就是前K个最小的元素

同样的,如果求的是前K个最大的数据,则创建一个容量为K的小根堆,然后堆顶元素和数组中的元素进行比较,如果数组元素比堆顶元素大,则进行出队操作,然后将数组元素入队。

求前K个最大的数据的代码如下:

public int[] maxLestK(int[] array, int k) {
    int[] ret = new int[k];

    if(array == null || k <= 0) {
        return ret;
    }
    
    PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();

    for(int i = 0; i < k; i++) {
        priorityQueue.offer(array[i]);
    }

    for(int i = k; i < array.length; i++) {
        int top = priorityQueue.peek();
        
        if(array[i] > top) {
            priorityQueue.poll();
            priorityQueue.offer(array[i]);
        } 
    }
    
    for(int i = 0; i < k; i++) {
        ret[i] = priorityQueue.poll();
    }
    return ret;
}

priorityQueue的大根堆和小根堆问题

以添加元素3 和 13为例

这里也解释了前面无法将Student类添加入priorityQueue中的原因,无法进行comparator.compare,我们这里举例的Integer是继承了Comparable接口的

补充:

补充:如果没有比较器是如下方法

完!

相关文章:

  • 4. grafana(7.5.17)功能菜单简介
  • 15-最后一个单词的长度
  • 体验用ai做了个python小游戏
  • ECOLOGY流程表单字段由单行文本改成多行文本
  • DeepSeek + Claude 提升效果
  • 当C#邂逅Deepseek, 或.net界面集成deepseek
  • Weblogic 反序列化漏洞深度剖析与复现
  • MouseWithoutBorder鼠标指针闪烁、变大+AltTab有程序执行的问题解决方案
  • 【算法】787. 归并排序
  • 指标管理项目建设的高频问题和解决思路
  • 房屋价格 - 高级回归技术
  • Visual Studio Code 集成 Baidu Comate
  • Spring Boot 内置工具类
  • LeetCode刷题---哈希表---347
  • UE_C++ —— Container TMap
  • scratch猜年龄互动小游戏 2024年12月scratch四级真题 中国电子学会 图形化编程 scratch四级真题和答案解析
  • 问卷数据分析|SPSS实操之相关分析
  • Windows 图形显示驱动开发-IoMmu 模型
  • Docker 安装 Apache
  • HBuilderX中,VUE生成随机数字,vue调用随机数函数
  • 上海与世界|环城生态公园带是上海绿色发展新名片
  • 浙江首个核酸药谷落子杭州,欢迎订阅《浪尖周报》第23期
  • 重庆一高校75万采购市价299元产品?工作人员:正在处理
  • 巴基斯坦称回应挑衅,对印度发起军事行动
  • 国常会:研究深化国家级经济技术开发区改革创新有关举措等
  • 古埃及展进入百天倒计时,闭幕前168小时不闭馆