掌握优先级队列:提升效率的关键技巧

news2024/11/21 1:39:14

目录

  • 优先级队列的概念
  • 优先级队列的模拟实现
    • 堆的创建
    • 堆的插入与删除
      • 堆的插入
      • 堆的删除
    • 用堆模拟实现优先级队列
  • 常见接口了解
    • PriorityQueue的几种常见构造方法

优先级队列的概念

队列是一种先进先出的数据结构,但在一些情况下我们要优先处理一些情况,比如:正在手机上打游戏的时候,如果有来电,那么系统就应该处理打进来的电话。
在这种情况下,数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。
在这里插入图片描述

优先级队列的模拟实现

DK1.8中的PriorityQueue底层使用了堆这种数据结构,而堆实际就是在完全二叉树的基础上进行了一些调整。因此我们先来模拟堆的创建,插入与删除。

堆的创建

堆的创建代码:

   //找倒数第一个非叶子节点,从该节点位置开始往前一直到根节点,遇到一个节点就使用向下调整
    public  void  creatHeap(int[] arr){
    int root = (arr.length-2)/2;
        for (; root>=0 ; root--) {
            shiftDown(arr,root);
        }
    }

建堆的时间复杂度为O(N)
堆的向下调整代码(以创建大堆代码为例):

    public void shiftDown(int[] arr, int parent){
        // child先标记parent的左孩子,因为parent可能右左没有右
    int child = parent*2+1;
    int size = arr.length;
    while (child < size){
        // 如果右孩子存在,找到左右孩子中较大的孩子,用child进行标记
        if(child+1 < size && arr[child] < arr[child+1]){
            child++;
        }
        // 如果双亲比其最大的孩子还小,则交换
        if(arr[child]>parent){
            int temp = arr[child];
            arr[child] = arr[parent];
            arr[parent] = temp;
        }else {
            break;
        }
        parent = child;
        child = (parent*2)+1;
    }
    }

堆的插入与删除

堆的插入

堆的插入总共需要两个步骤:

  1. 先将元素放入到底层空间中(注意:空间不够时需要扩容)
  2. 将最后新插入的节点向上调整,直到满足堆的性质
public void push(int val) {
      if(isFull()){
          return;
      }
      //usedSize为堆中元素个数
      elem[usedSize]=val;
      usedSize++;
      shiftUp(usedSize-1);
    }


向上调整:

 private void shiftUp(int child){
        // 找到child的双亲
        int parent = (child-1)/2;
        while (parent >= 0){
            if(arr[parent]>=arr[child]){
                break;
            }else {
                // 将双亲与孩子节点进行交换
                int temp = arr[parent];
                arr[parent] = arr[child];
                arr[child] = temp;
                child = parent;
                parent = (child-1)/2;
            }
        }
    }

堆的删除

堆的删除一定删除的是堆顶元素。具体如下:

  1. 将堆顶元素对堆中最后一个元素交换
  2. 将堆中有效数据个数减少一个
  3. 对堆顶元素进行向下调整
 public void pollHeap() {
        if(isEmpty()){
            return;
        }
        elem[0] = elem[usedSize-1];
        usedSize--;
        shiftDown(0,usedSize);
    }

用堆模拟实现优先级队列

 public class MyPriorityQueue { 
 private int[] array = new int[100];   
 private int size = 0;
 //入队
 public void offer(int e) {
 array[size++] = e;
 //向上调整
 shiftUp(size - 1);
 }
 //出队
 public int poll() {
 int oldValue = array[0];
 array[0] = array[--size];
 //向下调整
 shiftDown(0);
 return oldValue;
 }
 //出堆首元素
 public int peek() {
 return array[0];
 }
 }

常见接口了解

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

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

PriorityQueue的几种常见构造方法

构造器功能介绍
PriorityQueue()创建一个空的优先级队列,默认容量是11
PriorityQueue(int initialCapacity)创建一个初始容量为initialCapacity的优先级队列,注意:initialCapacity不能小于1,否则会抛IllegalArgumentException异常
PriorityQueue(Collection<? extends E> c)用一个集合来创建优先级队列

我们可以使用优先级队列解决一些问题,例如TOPK问题:最大或者最小的前k个数据。
思路就是我们求最大的前k个数据,我们用数据的前k个数字建一个小堆,然后依次拿堆顶元素与剩下的数据进行比较,如果那个数据大于堆定元素就进行互换,直到遍历完剩下的数据,堆中k个数据就为最大的k个数据。堆顶元素就为第k大元素。
总结思路就是:

  1. 用数据集合中前K个元素来建堆
    前k个最大的元素,则建小堆
    前k个最小的元素,则建大堆
  2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
    将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

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

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

相关文章

B2R Raven: 2靶机渗透

B2R Raven: 2靶机渗透 视频参考&#xff1a;ajest &#xff1a;https://www.zhihu.com/zvideo/1547357583714775040?utm_id0 原文参考&#xff1a;ajest &#xff1a;https://www.zhihu.com/column/c_1403138803561816064 原文参考&#xff1a;ajest https://zhuanlan.zhih…

从0备战蓝桥杯:找出只出现一次的数字,数单身狗

前言&#xff1a;在部分大厂笔试时经常会使用OJ题目&#xff0c;这里对《剑指offer》中的俩个题目进行思路分析和讲解&#xff0c;希望对各位读者有所帮助。 题目来源选自力扣网 目录&#xff1a; 单个只出现一次的数字&#xff1a; 力扣链接&#xff1a; 题目描述 &#xf…

1.Vue-在独立页面实现Vue的增删改查

题记 在独立页面实现Vue的增删改查&#xff0c;以下是具体的代码&#xff0c;和操作流程。 编写index.html页面 index.html文件如下&#xff1a; <!DOCTYPE html> <html> <head><title>Vue CRUD Example</title><!--在线导入vue文件-->&l…

【网络协议】聊聊网络分层

常用的网络协议 首先我们输入www.taobao.com&#xff0c;会先经过DNS进行域名解析&#xff0c;转换为59.82.122.115的公网IP地址。然后就会发起请求&#xff0c;一般来说非加密的使用http&#xff0c;加密的使用https。上面是在应用层做的处理&#xff0c;那么接下来就是到传输…

Ansible运行临时命令及常用模块介绍

目录 一.运行临时命令 1.基本语法格式 2.查看当前版本已安装的所有模块 二.ansible常见模块 1.command模块 2.shell模块 3.raw模块 4.script模块 5.file模块 参数列表&#xff1a; 示例&#xff1a; 6.copy模块 参数列表&#xff1a; 示例&#xff1a; 7.fetch模…

SSL证书能选择免费的吗?

当涉及到保护您的网站和您的用户的数据时&#xff0c;SSL证书是必不可少的。SSL证书是一种安全协议&#xff0c;用于加密在Web浏览器和服务器之间传输的数据&#xff0c;例如信用卡信息、登录凭据和个人身份信息。 但是&#xff0c;许多SSL证书都是付费的&#xff0c;这可能会…

Java应用的混淆、加密以及加壳

文章目录 前言问题代码混淆存在的问题Java类文件加密存在的问题虚拟化保护存在的问题AOT编译存在的问题 Java应用的打包混淆器类加载与类加密Bootstrap Class LoaderExtension Class LoaderSystem Class Loader自定义ClassLoaderprotector4j 加壳采用Golang打包Java程序xjar 参…

基于未来搜索优化的BP神经网络(分类应用) - 附代码

基于未来搜索优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于未来搜索优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.未来搜索优化BP神经网络3.1 BP神经网络参数设置3.2 未来搜索算法应用 4.测试结果…

2023年四川省安全员B证证考试题库及四川省安全员B证试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年四川省安全员B证证考试题库及四川省安全员B证试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大…

Filebeat 采集 k8s Pod 和 Events 日志实战操作

文章目录 一、概述1&#xff09;采集 Pod 日志流程介绍3&#xff09;采集 Events 日志流程介绍 二、K8s 集群部署三、ElasticSearch 和 kibana 环境部署四、Filebeat 采集配置1&#xff09;采集 Pod 日志配置2&#xff09;采集 Events 日志配置1、创建 filebeat 授权 token2、f…

网络 | 排错五大步骤,没有解决不了的网络故障准达信息准达信息

网络故障是我们工作中最易常见的问题&#xff0c;那么如何才能进行网络排查&#xff0c;快速解决问题呢&#xff1f; 一、网络排错五大基本步骤与命令 五大基本思路如下&#xff1a; &#xff08;1&#xff09;检查物理链路是否有问题&#xff1b; &#xff08;2&#xff09;…

【总结】两个独立同分布的随机变量相加还是原来的分布吗?

二项分布&#xff0c;泊松分布&#xff0c;正态分布&#xff0c;卡方分布&#xff0c;具有独立可加性。 图源自没咋了&#xff0c;面哥课程。

【软考】9.3 二叉树存储/遍历/线索/最优/查找/平衡

《树与二叉树》 二叉树的顺序存储结构 顺序存储只适用于完全二叉树和满二叉树&#xff0c;一般二叉树不适用i 2 的左孩子为 2i 4&#xff0c;右孩子为 2i 1 5 二叉树的链式存储结构 链式存储适用于二叉树&#xff1b;空结点用“∧”表示二叉链表&#xff1a;左孩子&#xff0…

论文阅读:CenterFormer: Center-based Transformer for 3D Object Detection

论文地址&#xff1a;[2209.05588] CenterFormer: Center-based Transformer for 3D Object Detection (arxiv.org) 代码地址&#xff1a;GitHub - TuSimple/centerformer: Implementation for CenterFormer: Center-based Transformer for 3D Object Detection (ECCV 2022) …

Java多线程下载文件

JVM是支持多线程程序的&#xff0c;当程序需要同时执行两个或多个任务&#xff0c;实现一些需要等待的任务时&#xff0c;如用户输入、文件读写、网络操作、搜索等多线程程序比单线程程序更具优势&#xff0c;可充分利用CPU资源&#xff0c;完成时间更短&#xff0c;提高应用程…

代码管理工具 gitlab实战应用

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 第七章 Spring Cloud 之 GateWay 第八章 Sprin…

Dokcer基础操作命令演示

Docker中的常见命令&#xff0c;可以参考官方文档&#xff1a;https://docs.docker.com/engine/reference/commandline/cli/ 1、命令介绍 其中&#xff0c;比较常见的命令有&#xff1a; 命令说明文档地址docker pull拉取镜像docker pulldocker push推送镜像到DockerRegistr…

【大数据】Apache Hive数仓(学习笔记)

一、数据仓库基础概念 1、数仓概述 数据仓库&#xff08;数仓、DW&#xff09;&#xff1a;一个用于存储、分析、报告的数据系统。 OLAP&#xff08;联机分析处理&#xff09;系统&#xff1a;面向分析、支持分析的系统。 数据仓库的目的&#xff1a;构建面向分析的集成化数据…

【Eclipse】Plug-in Development 插件的安装

先按路线找到需要的页面&#xff1a;eclipse–Window–Preferences–Java–Editor–Content Assist 在Work with框中输入&#xff1a;http://download.eclipse.org/releases/2019-06 PS&#xff1a;后面的2019-06是eclipse发行的时间 选择&#xff1a;General Purpose Tools 下…

TwinCAT3添加伺服控制器的方法

文章目录 一. 主要参考二. 使用嵌入式控制器CX5140添加三菱MR-J4-TM伺服控制器的方法具体步骤 一. 主要参考 《TwinCAT NC 使用指南》第四章 TwinCAT NC 控制总线伺服 二. 使用嵌入式控制器CX5140添加三菱MR-J4-TM伺服控制器的方法 嵌入式控制器: 倍福CX5140伺服控制器&…