Java数据结构7(优先级队列)

【Unity动画系统】详解Root Motion动画在Unity中的应用(一) 什么时候勾选Bake into pose,当不希望动画带动游戏对象旋转时。在旋转的动画中一般是不用勾选的,因为就需要用它来带动我们的角色对象旋转。但在比如前进、后退、待机等动画来说,我们就可以勾选这里,以避免因动画文件本身的瑕疵而给我们带来的旋转。loop match:代表了这个动画在角度上的吻合度。如果这个动画在播放中转角过大,那么就会显示红色,告诉我们如果勾选bake into pose,则会带来不好的效果。 阅读详情

一,目录

1,概念

2,堆的创建及相关方法的实现

3,常用接口介绍

4,top(k)问题

5,堆排序

一,概念

前⾯介绍过队列,队列是⼀种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先 级,⼀般出队列时,可能需要优先级⾼的元素先出队列,该中场景下,使⽤队列显然不合适,⽐如: 在⼿机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话;初中那会班主任排座位 时可能会让成绩好的同学先挑座位。 在这种情况下,数据结构应该提供两个最基本的操作,⼀个是返回最⾼优先级对象,⼀个是添加新的 对象。这种数据结构就是优先级队列(Priority   Queue)。

优先级队列底层是使用了堆这种数据结构,而堆就是在完全二叉树的基础上进行了一些调整

二,创建及相关方法

堆主要分为大根堆和小根堆

这两种都是在完全二叉树的基础上进行调整得来的,大根堆就是每一棵树的根都是根及其左右子树中最大的,小根堆就是每一棵树的根都是根及其左右子树中最小的,所以也有一个特点就是大根堆中根节点是最大的元素,小根堆中根结点是最小的元素,如下80就是所有元素里最大的,13就是所有元素里最小的

一:创建

1,我们先根据堆的思想来创建一个大根堆,其中的parent和child均为下标

2,具体做法是先找到最后一个左孩子的父亲节点的下标:我们就按照上图的树,也就是找到5的下标,我们还要引入一些前情数据,usedsize为13,那么根据完全二叉树的公式就知道,不管是左孩子还是右孩子,他们的父亲节点都是-1再/2,所以父亲节点的下标为(usedsize-1-1)/2,所以初始的parent=(usedsize-1-1)/2,然后parent依次往上,然后进行一个向下的调整

3,接下来就是要完成向下调整的一个代码,具体操作就是在左右孩子节点中找到最大的,然后将他的下标标记为chlid,然后将他和父亲节点进行比较,观察是否需要交换,交换完,交换下来的那个值并不一定是待在那个地方的,可能还需要和下面的数值进行一个调整,所以让parent等于child,然后child乘2加1,继续进行一个调整,当不需要调整的时候,就退出循环

具体代码如下

public class TestHeap {
    public int[] elem;
    public int usedsize;

    public TestHeap(){
        this.elem = new int[15];
    }
    public void init(int[] array){
        for (int i = 0; i < array.length; i++) {
            elem[i]=array[i];
            usedsize++;
        }
    }
    //
    public void creatheap(){
        //先找到最后一颗子树的根节点的下标
        for (int parent = (usedsize-1-1)/2; parent >=0; parent--) {
            shelldown(parent, usedsize);
        }
    }
    //向下调整
    private void shelldown(int parent,int usedsize){
        //1,先取得左孩子节点的下标
        int child=parent*2+1;
        //调整到child小于usedsize的时候
        while (child<usedsize){
            //先取得左右孩子中最大的,并且得保证有右孩子的情况下,没有就直接不用变
            if (child+1<usedsize && elem[child]<elem[child+1]){
                child++;
            }
            //现在child里面存储的就是左右孩子里的最大值的下标,然后进行交换
            if (elem[child]>elem[parent]){
                swap(elem,parent,child);
                //只能保证调整了的是正确的,但是还得向下调整保证换完的也是大根堆
                parent=child;
                child=parent*2+1;
            } else {
                break;
            }
        }
    }
    //交换
    private void swap(int[] elem,int i,int j){
        int tmp=elem[i];
        elem[i]=elem[j];
        elem[j]=tmp;
    }
}

二:相关方法

1,增加元素

public void offer(int val){
        //先判断有没有满,满了就得扩容
        if (isfull()){
            elem= Arrays.copyOf(elem,2*elem.length);
        }
        elem[usedsize]=val;
        siftup(usedsize);
        usedsize++;
    }

    private void siftup(int child) {
        int parent=(child-1)/2;
        //调整到parent>=0或者child>0的时候
        while (child>0){
            if (elem[child]>elem[parent]){
                swap(elem,child,parent);
                child=parent;
                parent=(child-1)/2;
            }else {
                break;
            }
        }
    }

    public boolean isfull(){
        return usedsize==elem.length;
    }

2,删除元素(头删)

public void pull(){
        if (isempty()){
            return;
        }
        //让首元素和最后一个元素交换
        swap(elem,elem[0],elem[usedsize-1]);
        usedsize--;
        //让首元素进行向下调整
        shelldown(0,usedsize);
    }
    public boolean isempty(){
        return elem.length==0;
    }
}

三,常用接口介绍

Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列, PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,本⽂主要介绍 PriorityQueue,PriorityQueue当中也有相应的方法,如offer,peek等

PriorityQueue<Integer> priorityQueue=new PriorityQueue<>();
        priorityQueue.offer(10);
        priorityQueue.offer(3);
        priorityQueue.offer(9);
        System.out.println(priorityQueue.peek());

我们通过peek方法可以知道系统自带的PriorityQueue是个小根堆,然后我们通过源码来看看它的构造方法,以及有没有方法来使其变成一个大根堆

通过源码的构造方法可以看出,有没有参数的也有两个参数的,其中的传入的比较器成为了关键

点入到offer方法里面可以发现有两种,一种是传入比较器,一种是使用默认的比较方法,所以我们只要写一个比较器,里面比较的方法根默认的是相反的话,那么就可以实现大根堆了,我来展示两种重写的比较方法

class imp implements Comparator<Integer>{
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2.compareTo(o1);
    }
}

第一种就是写一个比较器,在PriorityQueue调用的时候传入这个imp类就行了

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

第二种方法通过匿名内部类来实现

 什么是匿名内部类

没有名字的局部内部类,只用一次、用完就丢,不用单独新建 .java 文件写类;

只能实现一个接口 / 继承一个父类;

核心场景:快速实现函数式接口(Comparator、Runnable 等)。

四,top(k)问题

当我们要求一些数据的最大或者最小的k个的时候,我们可以用排序来找到前面的数据,当然也可以运用到堆,当我们要求前k个最小的数据的时候,我们可以创建一个大根堆,堆的数据个数为k,并且每次用下一个数据跟堆顶的元素进行比较,因为堆顶的数据肯定是k个中最大的,我们考虑换元素也是优先考虑它,具体代码如下

//top k问题
    public int[] smallk(int[] array,int k){
        //先判断数据
        int[] ret=new int[k];
        if (array==null||k==0){
            return null;
        }
        //创建一个大根堆
        PriorityQueue<Integer> priorityQueue=new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2.compareTo(o1);
            }
        });
        //将前k个数据放在大根堆里面
        for (int i = 0; i <= k; i++) {
            priorityQueue.offer(array[i]);
        }
        //将后面的数据跟堆顶进行比较,来调整堆
        int peekval=priorityQueue.peek();
        for (int i = k+1; i < array.length; i++) {
            if (peekval>array[i]){
                priorityQueue.poll();
                priorityQueue.offer(array[i]);
            }
        }
        for (int i = 0; i < k; i++) {
            int val=priorityQueue.poll();
            ret[i]=val;
        }
        return ret;
    }

五,堆排序

我们以从小到大来排序,就紧接在我们刚刚自己实现的大根堆下面,堆排序主要的思路就是找到堆顶元素,因为它是最大的,然后将其和最后一个元素进行交换,可以拿一个end下标来记录大的元素,end就等于usedsize-1,然后进行向下调整,最后调整到堆顶元素为最小值,然后依次增大

//从小到大排
    public void heapsort(){
        int end=usedsize-1;
        while (end>0){
            swap(elem,0,end);
            shelldown(0,end);
            end--;
        }
    }

自己的小问题以及理解:怎么理解创建堆的时候,传入的parent是最后一颗子树的父亲节点,但是后面我要自己调整的时候可以直接传入0下标

因为建堆的时候,所有数据都是乱给的,没有一个数据是排序好的,所以从最后一个往前调整,但是排序的时候,我们交换了最后一个以及堆顶的元素的时候,堆顶的左右子树都是完整的大根堆,已经是排序好的,所以堆顶的三个元素组成的树是需要调整的,所以传入0下标,然后后续下面有问题再shelldown里面也会接着调整

【LSTM回归预测】attention机制LSTM时间序列回归预测【含Matlab源码 1992期】 attention机制LSTM时间序列回归预测 完整的代码,方可运行;可提供运行操作视频!适合小白! 阅读详情

相关推荐

(7)栈 队列 优先级队列 《java数据结构与算法》一书第四章读书笔记。

------------------------------------------------------------------------------ 栈、队列、优先级队列 ------------------- 栈《刷盘子之后摞起来的盘子,最后放进去的,最先被使用。LIFO 后进先出。栈顶栈低。PUSH入栈 POP出栈》 栈只允许访问一个数据项:即最后插入的数据项。移除这个数据项后

pandaj的专栏 705

三维重建之条纹投影结构光(三)——相位展开优化与多频外差实践

本文深入探讨了三维重建中条纹投影结构光技术的核心环节——相位展开优化。针对传统路径跟踪法存在的误差传播与路径依赖问题,重点解析了多频外差法的原理与优势,并通过详细的C++代码实践,展示了如何利用三频外差法实现鲁棒、高精度的相位展开,从而获得连续的绝对相位图,为后续三维点云生成奠定坚实基础。

weixin_29074295的博客 532

Java中的优先级队列(PriorityQueue)(如果想知道Java中有关优先级队列的知识点,那么只看这一篇就足够了!)

Java中的优先级队列(PriorityQueue)(如果想知道Java中有关优先级队列的知识点,那么只看这一篇就足够了!)

秋刀鱼不做梦的编程日常 9503

STM32 使用IO口模拟I2C时序

上一篇《I2C协议详解》 我们了解了I2C的操作流程,这一篇,我们就使用I2C,来对EEPROM进行操作吧。 我们做两种选择: 1.时序由IO口模拟高低电平,需要了解协议并按照协议操作相应的IO口。 2.时序由硬件自行产生,不需要人工干预; 由硬件产生的I2C时序,我们借助Stm32Cube配置实现便可,我们这一篇,抛开Stm32Cube,手撕代码,根据I2C的时序,一步步地实现I2C对...

8937

实测对比:DECIMER、Img2Mol、MolScribe,哪个化学结构识别工具更靠谱?

化学结构识别(CSR)工具的核心任务是将分子结构图像转换为SMILES(Simplified Molecular Input Line Entry System)表示。这一过程需要克服图像质量差异、绘制风格变化以及特殊基团识别等挑战。三款工具采用不同的技术路线:DECIMER:基于EfficientNetV2+Transformer架构,优势在于处理标准期刊文献中的分子图示Img2Mol。

weixin_32576389的博客 348

【java-数据结构】Java优先级队列揭秘:堆的力量让数据处理飞起来

优先级队列(Priority Queue)是一种队列数据结构,其中每个元素都包含一个优先级,队列总是按元素的优先级顺序进行排序。与普通队列(先进先出 FIFO)不同,优先级队列确保每次从队列中移除的元素是具有最高优先级的元素。有些场景下,使⽤队列显然不合适,⽐如:在⼿机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话;初中那会班主任排座位时可能会让成绩好的同学先挑座位。在 Java 中,是基于堆的实现。

2301_80350265学无止尽5的博客 4283

2024年全国青少年信息素养大赛初赛真题(算法创意实践挑战赛C++小学组:带解析)

2024全国青少年信息素养大赛C++算法创意实践挑战赛初赛真题及解析

王老师青少年编程 2812

【数据结构与算法】详解什么是优先级队列,并用代码手动实现一个优先级队列

上一篇文章讲解了队列的相关知识,同时用代码实现了一个队列结构。那么本文将介绍一下另一种特殊的队列结构,叫做 优先级队列。 上一篇文章的跳转链接—— 公众号:Lpyexplore的编程小屋 关注我,每天更新,带你在python爬虫的过程中学习前端,还有更多电子书和面试题等你来拿 数据结构——优先级队列一、什么是优先级队列 一、什么是优先级队列 在了解了什么是队列以后,我们再来了解优先级队列,顾名思义,优先级队列就是在队列的基础上给每个元素加上了先后顺序,我们仍然拿排队买票的例子来讲解。 ...

零一的博客 2万+

QT应用编程: 编写低功耗BLE蓝牙调试助手(Android系统APP)

一、环境介绍 QT版本: 5.12.6 编译环境: win10 64位 目标系统: Android 完整工程源码下载地址(包含APK文件):https://download.youkuaiyun.com/download/xiaolong1126626497/19051696 二、功能介绍 本软件是一款BLE蓝牙串口调试助手,支持常规的发送和接收调试,BLE是低功耗类型蓝牙,在智能家居、物联网领域使用较多。BLE低功耗蓝牙一般不能直接使用手机进行连接,手机蓝牙默认都是工作在传统蓝牙模式,无法直接连接BL..

7661

matlab 点云可视化(1)——pcshow()函数可视化单个点云

matlab可视化单个点云常用方法汇总。

点云侠的博客 5361

数据结构7 --- 优先级队列

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

L1iiowo_666的博客 918

Python爬虫实战:绕过Cloudflare反爬的最新技术与完整代码详解

在互联网数据采集领域,越来越多的网站开始部署CDN和安全防护服务,其中 Cloudflare 是最为广泛使用的防护方案之一。它不仅为网站提供DDoS防护,还能通过JS挑战、验证码和行为分析来识别并拦截爬虫。这给爬虫工程师带来了极大挑战——如何在不违反网站服务条款的情况下,实现有效的数据采集?本文将分享Python领域绕过Cloudflare反爬的最新技术方法,结合最新流行库与自动化浏览器,帮助你攻克这一难题。绕过Cloudflare反爬不是一蹴而就,需结合多技术、多策略,持续迭代。

2201_76125261的博客 2628

Java数据结构——优先级队列(堆)

前面知道了队列这种数据结构,为了让其出队列具有优先级就有了优先级队列(堆),下面就来详细介绍一下

2401_89019969的博客 1196

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

优先级队列简要分析与实现(Java)

本文对优先级队列进行简要分析,并分析实现了基于无序数组和有序数组的方案,同时给出了基于堆的实现方案。

ArrebolMKJ的博客 1402

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

数据结构之优先级队列【堆】(Heap)

(1)优先级队列底层是堆来实现的 (2)堆的本质是完全二叉树 ,堆有大根堆和小根堆 (3)大根堆:根节点最大的堆; 小根堆:根节点最小的堆 (6)top-K问题:前K个最大的元素建小根堆;前K个最小的元素建大根堆 第K个最大元素建小根堆 拿栈顶; 第K个最小元素建大根堆 拿栈顶 (7)堆排序:升序:大根堆 降序:小根堆 核心思想:堆元素的删除...

m0_58761900的博客 3141

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Java数据结构(七)——优先级队列与PriorityQueue

文章基于Java集合框架中的PriorityQueue类,先介绍了堆的相关知识,而后介绍了PriorityQueue的使用。

xiaokuer_的博客 1527

数据结构--优先级队列

数据结构--优先级队列(堆)一级目录二级目录三级目录 一级目录 二级目录 三级目录

weixin_47230102的博客 984

【Java 数据结构】 优先级队列(堆)

学习目标: 目标:熟练掌握Java所学知识 学习内容: 本文内容:优先级队列(堆) 文章目录学习目标:学习内容:一、优先级队列1.1 概念1.2常用接口介绍1.2.1 PriorityQueue特性1.2.2 PriorityQueue常用接口介绍1.3 优先级队列的应用二、优先级队列的模拟实现2.1堆的概念2.2堆的存储方式2.3 堆的创建2.3.1 堆向下调整2.3.2 堆的向上调整2.3.3删除堆顶元素2.3.4取堆顶元素 一、优先级队列 1.1 概念 队列是一种先进先出的数据结构(FIFO)。但

zhangxxin的博客 234

java实现 数据结构:链表、 栈、 队列、优先级队列、哈希表

最近在准备找工作的事情,就复习了一下java。翻了一下书和网上的教材,发现虽然很多书是用java讲数据结构的,但是侧重于将数据结构本身的知识,利用java本身的类库来实现数据结构的系统性的讲解少之又少,所以在此做一下总结,方便各位正在准备工作的和用java实现数据结构的朋友们。 附:代码下载:http://download.youkuaiyun.com/detail/sunnyskyliu/4754827

4124

Java数据结构第十八期:探索优先级队列的魅力(二)

我们来看一下Integer里面的源码,在Structure里面找到compare(int ,int),因为10>5,进不来上面的循环,就可以走下面的代码,再把0下标给到5元素,从而实现小根堆。除此之外,还有第三种解法,就是利用大根堆。先建立一个大小为k的大根堆,从数组的第k+1个元素开始遍历数组,如果数组元素比堆顶元素小,则交换,遍历结束之后,大根堆里的元素就是最小k个数。offer的源码如下,从下面的逻辑中可以看出,它的向上调整是一个一个实现的,而不是直接去调整一个数组,所以下面的时间复杂度是。

2401_85198927的博客 1227

数据结构 Java数据结构 ---- 堆(优先级队列)

文章目录堆(优先级队列)1.二叉树的顺序存储1.1 存储方式1.2 下标的关系2.堆2.1 概念3.模拟实现PriorityQueue①基本操作②向下调整③建堆④入队列⑤出队列⑥堆排序4.堆的应用-优先级队列4.1 java 中的优先级队列4.2 java 中堆的使用5. 集合框架中PriorityQueue的比较方式6.堆的其他应用-TopK 问题用堆的思路:画图解析:代码实现:运行结果:7.面试题---查找和最小的K对数字解题思路:代码实现: 堆(优先级队列) 1.二叉树的顺序存储 1.1 存储方式 使

wwzzzzzzzzzzzzz的博客 2377

优先级队列(堆)(java数据结构)

Java集合框架中提供了和两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,本文主要介绍PriorityQueue。下面我们来演示一下是什么样的:这里我们往这个优先级队列里面放几个元素,这里没人告诉我们他是大根堆还是小根堆,这里我们peek一下这个元素,看我们拿到的是10(大根堆)还是5(小根堆).结果如下:如上结果意味着,当我们实例化一个PriorityQueue对象之后,其实默认是一个小根堆.

2301_76815082的博客 1017

优先级队列(PriorityQueue)-JAVA

优先级队列以及用堆的模拟实现详解

tao的博客 1670

【浅学Java数据结构】 优先级队列以及堆的创建、插入、删除

优先级队列 (PriorityQueue)1. 优先级队列1.1 概念2. 优先级队列的模拟实现2.1 堆的概念2.2 堆的存储方式3. 堆的创建3.1 堆的向下调整3.2 建堆的时间复杂度4. 堆的插入和删除4.1 堆的插入4.2 堆的删除5. 用堆模拟优先级队列6. 常用接口介绍6.1 PriorityQueue的特性6.2 PriorityQueue常用接口介绍7. 优先级队列的应用 1. 优先级队列 1.1 概念 前面介绍过队列,队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数

qq_52276036的博客 1997

【Java数据结构】优先级队列详解(二)

所以这篇文章我们就把堆(priorityqueue)的使用讲述清楚了,堆也就此完结了,花了两篇文章去讲解。之后将给大家带来排序的讲解。让我们共同学习,共同进步,为知识的海洋增添更多宝贵的财富!

Easonmax的博客 1219
上一篇: Java数据结构6(队列和二叉树初步)
下一篇: 常见排序汇总--你都了解吗?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值