优先级队列

简介: 优先级队列

前言:

普通的队列是一种 先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用 数据结构来实现。

在下面这篇文章中讲解了堆。

1、PriorityQueue的特性

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

查看源码发现:PriorityQueue继承了AbstractQueue,并且初始容量为11,AbstractQueue又实现了Queue接口


921ce77aaada496282d0a8ade14ff150.pngadc7b7f73bcd4db8850d5b64db35610a.png

c8ba7ec814f6433e84100172ae3d6329.png

关于PriorityQueue的使用要注意:

  1.  使用时必须导入PriorityQueue所在的包,即:
import java.util.PriorityQueue;
  1. PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出 ClassCastException异常
  2. 不能插入null对象,否则会抛出NullPointerException
  3.  没有容量限制,可以插入任意多个元素,其内部可以自动扩容
  4. 插入和删除元素的时间复杂度为log₂N
  5. PriorityQueue底层使用了堆数据结构,
  6.  PriorityQueue默认情况下是小堆---即每次获取到的元素都是最小的元素(如果要设置为大根堆的话需要重写比较器来实现或者借助lambda表达式
package 选择排序;
import java.util.PriorityQueue;
public class 优先级队列 {
    public static void main(String[] args) {
        PriorityQueue<Integer> queue=new PriorityQueue<>();
        queue.offer(4);
        queue.offer(2);
        queue.offer(3);
        queue.offer(7);
        queue.offer(9);
        System.out.println(queue.peek());//2
    }
}

方法一:比较器

PriorityQueue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });

方法二:lambda表达式

Queue<Integer> queue = new PriorityQueue<>((o1, o2) -> o2 - o1);
import java.util.Comparator;
import java.util.PriorityQueue;
public class 优先级队列 {
    public static void main(String[] args) {
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        queue.offer(4);
        queue.offer(2);
        queue.offer(3);
        queue.offer(7);
        queue.offer(9);
        System.out.println(queue.peek());//2
        PriorityQueue<Integer> queue1=new PriorityQueue<>((o1, o2) -> o2-o1);
        queue1.offer(4);
        queue1.offer(2);
        queue1.offer(3);
        queue1.offer(7);
        queue1.offer(9);
        System.out.println(queue1.peek());//9
    }
}

2 PriorityQueue常用接口介绍

Ⅰ、PriorityQueue常见的构造方法


image.png

import java.util.PriorityQueue;
class Student implements Comparable<Student>{
    public int age;
    @Override
    public int compareTo(Student o) {//如果没有比较器,则下面添加时则会报错
        return this.age-o.age;
    }
}
public class 优先级队列 {
    public static void main(String[] args) {
        PriorityQueue<Student> queue=new PriorityQueue<>();
        queue.offer(new Student());
        queue.offer(new Student());
    }
}

因为PriorityQueue不能插入无法比较大小的对象,需要实现比较器。


09b3aab704e64092ae5339fec155e025.png

Ⅱ、常用的方法

Modifier and Type Method and Description
boolean
add(E e)
将指定的元素插入到此优先级队列中。
void clear()
从此优先级队列中册除所有元素。
Comparatore<? super E>

comparator(

返回用于为了在这个队列中的元素,或比较null如果此队列根据所述排序natural ordering的元素。

boolean contains(object o)
如果此队列包含指定的元素,则返回true.
Iteratore<E> iterator()
返回此队列中的元素的迭代器。
boolean offer(E e)
将指定的元素插入到此优先级队列中。
E peek ()
检素但不删除此队列的头,如果此队列为空,则返回null.
E poll()
检索并删除此队列的头,如果此队列为空,则返回null。
boolean remove(object o)
从该队列中删除指定元素的单个实例(如果存在)。
int size()
返回此集合中的元素数。
object[] toArray()
返回一个包含此队列中所有元素的数组。
<T>  T[]

toArray(T[]a)
返回一个包含此队列中所有元素的数组;返回的数组的运行时类型是指定数组的运行时类型。

Ⅲ、PriorityQueue的扩容方式:

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;
    }

优先级队列的扩容说明:

  • 如果容量小于64时,是按照oldCapacity2倍方式扩容的
  • 如果容量大于等于64,是按照oldCapacity1.5倍方式扩容的
  • 如果容量超过MAX_ARRAY_SIZE,按照MAX_ARRAY_SIZE来进行扩容




e7e9c12949e54d53b767af95ea682d89.png

3、应用

经典优先级队列问题——TOP-K问题:最大或者最小的前k个数据

面试题 17.14. 最小K个数 - 力扣(Leetcode)

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;
    }
}

692. 前K个高频单词 - 力扣(Leetcode)

这题既可以使用HashMap也可以使用优先级队列。


优先级队列思想

我们可以创建一个小根优先队列(顾名思义,就是优先队列顶端元素是最小元素的优先队列)。我们将每一个字符串插入到优先队列中,如果优先队列的大小超过了 k,那么我们就将优先队列顶端元素弹出。这样最终优先队列中剩下的 k个元素就是前 k 个出现次数最多的单词。











目录
相关文章
|
敏捷开发 Devops 测试技术
构建软件质量保障体系
构建软件质量保障体系
805 0
|
10天前
|
人工智能 运维 自然语言处理
2025 必藏 RPA 清单:从国际巨头到国产新锐,小白也能轻松上手的智能工具
RPA(机器人流程自动化)正成为企业数字化转型的核心工具,广泛应用于金融、电商、政务等领域。它如同“数字员工”,可自动完成重复性电脑操作,提升效率3-5倍且错误率低于0.1%。2025年全球市场规模达145亿美元,中国市场增速领先。本文盘点三款主流RPA工具:国际标杆UiPath、微软生态利器Power Automate,以及融合AI的国产新锐实在Agent,助力个人与企业高效选型,释放人力价值。
|
6月前
|
机器学习/深度学习 人工智能 编解码
智谱AI发布新版VLM开源模型GLM-4.1V-9B-Thinking,引入思考范式,性能提升8倍
视觉语言大模型(VLM)已经成为智能系统的关键基石。
1194 0
|
JavaScript Java 关系型数据库
Springboot+vue的校园社团管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。
Springboot+vue的校园社团管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。
|
11月前
|
中间件 关系型数据库 数据库
docker快速部署OS web中间件 数据库 编程应用
通过Docker,可以轻松地部署操作系统、Web中间件、数据库和编程应用。本文详细介绍了使用Docker部署这些组件的基本步骤和命令,展示了如何通过Docker Compose编排多容器应用。希望本文能帮助开发者更高效地使用Docker进行应用部署和管理。
343 19
|
机器学习/深度学习 数据采集 监控
构建高效机器学习模型的最佳实践
【4月更文挑战第25天】 在数据驱动的时代,机器学习已成为创新和效率提升的关键工具。本文将探讨一系列实用的策略和技术,旨在帮助读者构建出更高效、更精确的机器学习模型。我们将从数据处理开始,讨论特征选择的重要性以及如何避免过拟合,接着深入到模型选择与优化,最后讨论模型部署和维护的实践要点。通过遵循这些最佳实践,读者能够提升其机器学习项目的成功率并实现更好的业务成果。
|
算法 数据可视化
【视频】Copula算法原理和R语言股市收益率相依性可视化分析
【视频】Copula算法原理和R语言股市收益率相依性可视化分析
|
前端开发 IDE Java
用 Spring Boot 打包你的 React 应用
先讲一讲这篇文章的背景故事。之前我的团队需要在我们需求的基础架构上节省一些资金,并且由于我们要构建的这个应用程序中,大部分负载都会在客户端而非服务端上,所以我们决定试验一下能否将一个 Spring 应用程序与一个 React 应用结合起来,并打包成一个 war 文件。
|
Windows
模式匹配
模式匹配
170 0
|
1天前
|
人工智能 JavaScript Linux
【Claude Code 全攻略】终端AI编程助手从入门到进阶(2026最新版)
Claude Code是Anthropic推出的终端原生AI编程助手,支持40+语言、200k超长上下文,无需切换IDE即可实现代码生成、调试、项目导航与自动化任务。本文详解其安装配置、四大核心功能及进阶技巧,助你全面提升开发效率,搭配GitHub Copilot使用更佳。