PriorityQueue优先级队列

news2024/12/26 22:51:19

前言

优先级队列就是在堆的基础上进行改造,那么什么是堆,又什么是优先级队列呢?

我们一起来看看吧!

 


目录

前言

一、堆

(一)堆的创建

(二)堆的插入

(三)堆的删除

(四)模拟实现堆

二、优先级队列

(一)常用方法:

(二)常考点

结语


一、堆

堆就是堆中某个节点的值总是不大于或不小于其父节点的值。

堆总是完全二叉树。

Java底层的堆是顺序表,按照层序遍历的规则存储数据。

堆分为小根堆和大根堆。

1.小根堆(又名最小堆)

就是堆中某个节点的值总是不小于其父节点的值。

例如:

 

2.大根堆(又名最大堆)

就是堆中某个节点的值总是不大于其父节点的值。

 例如:

 

以创建最小堆为例,给出的数据顺序是: 5、3、6、7、4、2.

(一)堆的创建

首先,根据给出的数据顺序,创建如下二叉树:

 从最后一个叶子节点开始调整(向上调整):

时间复杂度是:O(n)

(二)堆的插入

假设要插入数据0:

如果在插入数据时,堆满扩容;调整为向上调整。 

时间复杂度是:O(log n)

(三)堆的删除

堆的删除一定删除的是堆顶元素。

时间复杂度是:O(log n) 

(四)模拟实现堆

代码:

import java.util.Arrays;
import java.util.Comparator;

class PriorityException extends RuntimeException{
    public PriorityException(String s){
        super(s);
    }
}


public class MyPriortyQueue implements Comparator<Integer> {
    public int[] elem;
    public int usedSize;

    public MyPriortyQueue(int k) {
        elem = new int[k];
    }

    public MyPriortyQueue() {
        elem = new int[11];
    }

    @Override
    public int compare(Integer o1,Integer o2) {
        return o2.compareTo(o1);
    }

    /**
     * 建堆
     */
    public void createHeap(int[] array) {
        for(int i = 0; i < array.length; i++){
            elem[i] = array[i];
            usedSize++;
        }
        for(int i = (usedSize-1-1)/2; i >= 0; i--){
            shiftDown(i,usedSize-1);
        }
    }

    /**
     * 向下调整
     * @param root 是每棵子树的根节点的下标
     * @param len  是每棵子树调整结束的结束条件
     * 向下调整的时间复杂度:O(logn)
     */
    private void shiftDown(int root,int len) {
        int child = root*2+1;
        while(child < len){
            if(child+1<len && compare(elem[child],elem[child+1])>0){
                child++;
            }
            if(compare(elem[root],elem[child])>0){
                int tmp = elem[root];
                elem[root] = elem[child];
                elem[child] = tmp;
                root = child;
                child = root*2+1;
            }else{
                break;
            }
        }
    }


    /**
     * 入队:仍然要保持是大根堆
     * @param val
     */
    public void push(int val) {
        if(isEmpty()){
            elem[0] = val;
        }else{
            elem[usedSize] = val;
        }
        usedSize++;
        shiftUp(usedSize-1);
    }
    /**
     * 向上调整
     * 默认除了需要调整的地方外,其余都是已经调整好了的
     */
    private void shiftUp(int child) {
        int parent = (child-1)/2;
        while(child > 0){
            if(compare(elem[parent],elem[child])>0){
                int tmp = elem[parent];
                elem[parent] = elem[child];
                elem[child] = tmp;
                child = parent;
                parent = (child-1)/2;
            }else{
                break;
            }
        }
    }

    public boolean isFull() {
        return usedSize == elem.length;
    }

    /**
     * 出队【删除】:每次删除的都是优先级高的元素
     * 仍然要保持是大根堆
     */
    public void pollHeap() throws PriorityException{
        if(isEmpty()){
            throw new PriorityException("pollHeap::队列无元素,删除失败");
        }
        elem[0] = elem[usedSize-1];
        usedSize--;
        shiftDown(0, usedSize-1);
    }

    public boolean isEmpty() {
        return usedSize == 0;
    }

    /**
     * 获取堆顶元素
     * @return
     */
    public int peekHeap() throws PriorityException{
        if(isEmpty()){
            throw new PriorityException("peekEmpty::队列无元素,获取失败");
        }
        return elem[0];
    }

    public static void main(String[] args) {
        MyPriortyQueue p = new MyPriortyQueue();
        int[] arr = {2,4,2,5,7,9,5,3};
        p.createHeap(arr);
        System.out.println("+=========创建一个堆========+");
        System.out.println(Arrays.toString(p.elem));
        p.push(10);
        System.out.println("+=========入一个值========+");
        System.out.println(Arrays.toString(p.elem));
        System.out.println("+=========输出堆顶========+");
        System.out.println(p.peekHeap());
        p.pollHeap();
        System.out.println("+=========删除堆顶=======+");
        System.out.println(Arrays.toString(p.elem));
    }
}

代码链接在GitHub:堆_练习模拟实现2 · Yjun6/DataStructrue@98faae5 (github.com)

二、优先级队列

PriorityQueue<Integer> p = new PriorityQueue<>();

(一)常用方法:

boolean offer(E e)插入元素e,成功插入返回true;会自动扩容;如果e为空,会抛出异常
E peek()获取优先级队列最高的元素;若队列为空,返回null
E poll()移除优先级队列最高的元素;若队列为空,返回null
int size()获取有效元素个数
void clear()清空
boolean isEmpty()判断是否为空

关于创建优先级队列的方法:

PriorityQueue()初始容量为11,默认无比较器
PriorityQueue(int k)初始容量为k,k>0
PriorityQueue(Collection<? extend E> c)用一个集合创建优先级队列

优先级队列扩容说明:

  • 如果容量小于64,按照2倍扩容;
  • 如果容量大于等于64,按照1.5倍扩容;
  • 如果容量超过 MAX_ARRAY_SIZE,按照 MAX_ARRAY_SIZE 进行扩容。

(二)常考点

求前k个最大值、前k个最小值、第k个最大值、第k个最小值……

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

代码:

class Solution {
    public int[] smallestK(int[] arr, int k) {
        if(arr == null || k == 0) return new int[k];
        Comp comp = new Comp();
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(comp);//求大根堆
        for(int i = 0; i < k; i++){
            priorityQueue.offer(arr[i]);
        }
        for(int i = k; i < arr.length; i++){
            if(arr[i] < priorityQueue.peek()){
                priorityQueue.poll();
                priorityQueue.offer(arr[i]);
            }
        }
        int[] str = new int[priorityQueue.size()];
        for(int i = 0; i < str.length; i++){
            str[i] = priorityQueue.poll();
        }
        return str;
    }
}


class Comp implements Comparator<Integer> {
    @Override
    public int compare(Integer a, Integer b){
        return b.compareTo(a);
    }
}

结语

小编能力有限,欢迎大家指出错误哦~

这篇博客如果对你有帮助,给博主一个免费的点赞以示鼓励,欢迎各位🔎点赞👍评论收藏⭐,谢谢!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/579527.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

win10 nvprof的性能分析表

交叉访问是全局内存中最糟糕的访问模式&#xff0c;因为它浪费总线带宽 使用多个线程块对基于交叉的全局内存访问重新排序到合并访问 https://mp.weixin.qq.com/s/h2XKth1bTujnrxyXTJ2fwg <<<numBlocks, blockSize>>> 的两个参数应该怎么设置好呢。首先&…

lazada商品评论数据接口,支持多站点

可以使用Lazada的开放平台API来获取商品评论数据。以下是使用API获取Lazada商品评论数据的基本步骤&#xff1a; 1.注册Lazada开发者账号&#xff0c;创建API密钥和访问令牌。 2.调用Lazada Open API中的Product Review API&#xff0c;提供商品的SKU或Seller SKU参数&#x…

Spring Authorization Server 系列(二)获取授权码

Spring Authorization Server 系列&#xff08;二&#xff09;获取授权码 概述获取授权码获取授权码的url逻辑解析匹配url参数解析 三级目录 概述 Spring Authorization Server 是基于 OAuth2.1 和 OIDC 1.0 的。 只有 授权码&#xff0c;刷新token&#xff0c;客户端模式。 …

Python GUI:真的只知道PyQt?

B站|公众号&#xff1a;啥都会一点的研究生 有时候我们有需求将程序制作成GUI&#xff08;图形用户界面&#xff09;格式&#xff0c;以方便用户通过图形图标与电子设备进行交互&#xff0c;而大多数像我一样的小白基本上只知道PyQt&#xff0c;往往制作出来的界面一眼就可辨别…

如何编写快速高效的SQL查询(一)——MySQL8.0优化器查询优化处理与样例

当希望MySQL能够以更高的性能运行查询时&#xff0c;最好的办法就是弄清楚MySQL是如何优化和执行查询的。一旦理解了这一点&#xff0c;很多查询优化工作实际上就是遵循一些原则让优化器能够按照预想的合理的方式运行。 MySQL是如何执行一个查询的过程的&#xff1f;根据图8-1可…

SpringCloud高级篇 - 微服务保护

✨作者&#xff1a;猫十二懿 ❤️‍&#x1f525;账号&#xff1a;CSDN 、掘金 、个人博客 、Github &#x1f389;公众号&#xff1a;猫十二懿 学习课程视频 SpringCloud 高级篇 – 微服务保护 1.初识Sentinel 1.1.雪崩问题及解决方案 1.1.1.雪崩问题 微服务中&#xff0…

Spring IOC体系结构设计原理详解

Spring是一个开源的JavaEE全栈框架&#xff0c;其中最为重要的核心模块是Spring IOC&#xff08;Inversion of Control&#xff09;容器。它负责对象的生命周期管理及依赖注入&#xff0c;为开发者提供了一种主动参与对象创建过程的方式。本文将从IOC容器的设计原理出发&#x…

新增ES6中的扩展

1. ES6中数组新增了哪些扩展&#xff1f; Rest 参数与 Spread 语法 在 JavaScript 中&#xff0c;很多内建函数都支持传入任意数量的参数。 例如&#xff1a; Math.max(arg1, arg2, ..., argN) —— 返回参数中的最大值。Object.assign(dest, src1, ..., srcN) —— 依次将属…

Java 修饰符关键字

&#x1f49f;这里是CS大白话专场&#xff0c;让枯燥的学习变得有趣&#xff01; &#x1f49f;没有对象不要怕&#xff0c;我们new一个出来&#xff0c;每天对ta说不尽情话&#xff01; &#x1f49f;好记性不如烂键盘&#xff0c;自己总结不如收藏别人&#xff01; static …

【图神经网络】手把手带你快速上手OpenHGNN

手把手带你快速上手OpenHGNN 1. 评估新的数据集1.1 如何构建一个新的数据集 2. 使用一个新的模型2.1 如何构建一个新模型 3. 应用到一个新场景3.1 如何构建一个新任务3.2 如何构建一个新的trainerflow 内容来源 1. 评估新的数据集 如果需要&#xff0c;可以指定自己的数据集。…

【ROS】服务通信、话题通信的应用

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法…感兴趣就关注我吧&#xff01;你定不会失望。 服务通信、话题通信的应用 0. 话题发布1.话题订阅2.服务调用3.话题通信与服务通信的比较 本章将来学习如何利用话题通信&#xff0c;服务…

【软件分析/静态分析】学习笔记02——中间表示Intermediate Representation

&#x1f517; 课程链接&#xff1a;李樾老师和谭天老师的&#xff1a;南京大学《软件分析》课程02&#xff08;Intermediate Representation&#xff09;_哔哩哔哩_bilibili 目录 第二章 Intermediate Representation 2.1 编译器与静态分析器的关系(Compilers & Static …

SpringCloudAlibaba(简介及核心组件使用)

微服务架构常见的问题 一旦采用微服务系统架构&#xff0c;就势必会遇到这样几个问题&#xff1a; 这么多小服务&#xff0c;如何管理他们&#xff1f;服务发现/服务注册---》注册中心 这么多小服务&#xff0c;他们之间如何通讯&#xff1f;Feign -> 基于 http 的微服务调…

使用【Python+Appium】实现自动化测试

一、环境准备 1.脚本语言&#xff1a;Python3.x IDE&#xff1a;安装Pycharm 2.安装Java JDK 、Android SDK 3.adb环境&#xff0c;path添加E:\Software\Android_SDK\platform-tools 4.安装Appium for windows&#xff0c;官网地址 Redirecting 点击下载按钮会到GitHub的…

使用golang 基于 OpenAI Embedding + qdrant 实现k8s本地知识库

使用golang 基于 OpenAI Embedding qdrant 实现k8s本地知识库 文章博客地址:套路猿-使用golang 基于 OpenAI Embedding qdrant 实现k8s本地知识库 流程 将数据集 通过 openai embedding 得到向量组装payload,存入 qdrant用户进行问题搜索,通过 openai embedding 得到向量,从…

“Jmeter WebSocket协议压测”,助你轻松应对高并发场景!

目录 引言 背景说明 步骤1&#xff1a;安装插件JMeter WebSocket Samplers 步骤2&#xff1a;采集器使用 步骤3&#xff1a;脚本执行 结语 引言 在当今高并发的网络环境下&#xff0c;WebSocket协议已经成为了最受欢迎的实时通信技术之一。然而&#xff0c;对于开发人员来…

CorelDRAW2023序列号及下载安装条件

始于1989年并不断推陈出新,致力为设计工作者提供更高效的设计工具&#xff01;CorelDRAW滋养并见证了一代设计师的成长&#xff01;在最短的时间内交付作品&#xff0c;CorelDRAW的智能高效会让你一见钟情&#xff01;CorelDRAW 全称“CorelDRAW Graphics Suite“&#xff0c;也…

Linux:命令tar、zip、unzip对文件或文件夹进行压缩与解压

Linux&#xff1a;命令tar、zip、unzip对文件或文件夹进行压缩与解压 .tar压缩操作&#xff1a; 创建要进行压缩的文件&#xff1a; 对文件进行压缩&#xff1a; 将三个文件压缩成text.tar文件&#xff0c;压缩到当前路径下(默认也是在当前路径) 对比体积&#xff1a; 发现&…

关于f-stack转发框架的几点分析思考

使用DPDK收包&#xff0c;想要用到TCP协议栈&#xff0c;可选的方案有linux原生的tun/tap口以及DPDK自带的KNI驱动&#xff0c;这两种都是通过将DPDK收到的报文注入到linux内核来使用TCP协议栈的功能&#xff0c;然后&#xff0c;用户态协议栈可以考虑开源的f-stack&#xff0c…

在页面使用富文本编译器

富文本编译器的选择 Editor.mdTinyMCESimpleMDECKEditor 还有一些&#xff0c;这里讲的是我用的TinyMCE 1、下载 下载地址&#xff1a;下载tiny | TinyMCE中文文档中文手册 下载开发版本&#xff0c;我下载的最新版 tinymce_6.4.2_dev.zip 将压缩包解压后可以看到下面目录&…