堆的基本操作和PriorityQueue接口

news2024/10/6 16:30:30

目录

堆的插入

堆的删除

PriorityQueue接口

PriorityQueue的注意事项:

PriorityQueue常用接口介绍

  1. 优先级队列的介绍

  2.  扩容

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

Java对象的比较

       1.基本类型的比较

       2.对象比较的问题

       3.对象比较的方法

Top- k问题


堆的插入

堆的插入总共分为两个步骤:

        1:先将元素放到底层空间中(空间不够的时候要扩容)

        2:将新插入的节点向上调整,直到满足大根堆或者小根堆的性质(以大根堆为例)

代码实现:

public void offer(int val) {
        if(isFull()) {
            //扩容
            Arrays.copyOf(elem,2*elem.length);
        }
        //放到最后一个位置
        elem[usedSize++] = val;
        //向上调整
        shiftUp(usedSize- 1);
    }
    //判断是否满了
    public boolean isFull() {
        return usedSize == elem.length;
    }
    //向上调整
    private void shiftUp(int child) {
        int parent = (child-1) / 2;
        while(child > 0) {
            if(elem[child] > elem[parent]) {
                int tmp = elem[child];
                elem[child] = elem[parent];
                elem[parent] = tmp;
                child = parent;
                parent = (child-1) / 2;
            } else {
                break;
            }
        }
    }

向上调整建堆的时间复杂度:


 堆的删除

注意:堆的删除一定是删除堆顶元素

        1: 将堆顶元素和堆中有效数据的最后一个数据交换

        2: 将有效长度减1(最后一个元素就被删除)

        3: 对堆顶元素进行向下调整

代码实现:

public void pop(int val) {
        if(isEmpty()) {
            return;
        }
        int tmp = elem[0];
        elem[0] = elem[usedSize-1];
        elem[usedSize-1] = tmp;
        usedSize--;
        shifDown(0,usedSize);
    }
    //判断是否为空
    public boolean isEmpty() {
        return usedSize == 0;
    }
    //向下调整
    public void shifDown(int parent,int len) {
        int child = 2 * parent + 1;
        //最起码有一个左孩子
        while (child < len) {
            //有右孩子的情况
            if (child + 1 < len && elem[child] < elem[child + 1]) {
                //保证child下标是左右孩子最大值下标
                child++;
            }
            if (elem[child] > elem[parent]) {
                int tmp = elem[child];
                elem[child] = elem[parent];
                elem[parent] = tmp;
                parent = child;
                child = 2 * parent + 1;
            } else {
                break;
            }
        }
    }

PriorityQueue接口

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


PriorityQueue的注意事项:

1. 在使用PriorityQueue时要导入所在包

2. PriorityQueue中放置的元素必须能够比较大小,不能插入无法比较大小的对象,否则会抛出classCastException.

3. 不能插入null对象,否则会抛出NUllPointException.

4. 没有容量限制,可以任意插入多个元素,其内部可以自动扩容

5. 插入和删除的时间复杂度为O(log2 N)

6. PriorityQueue底层使用了堆数据结构

7. PriorityQueue默认底层为小根堆.每次获取到的都是最小的元素.


PriorityQueue常用接口介绍

        1. 优先级队列的介绍

代码实现 :

  一般在创建优先级队列对象时,如果知道元素个数,建议就直接将底层容量给好
  否则在插入时需要扩容
扩容机制:开辟更大的空间,拷贝元素,这样效率会比较低
     

  2.  扩容

  优先级队列的扩容说明 :
        1. 如果容量小于64时,按照oldCapacity的2倍扩容
        2. 如果容量大于64时,按照oldCapacity的1.5倍扩容
        3. 如果容量大于MAX_ARRAY_SIZE,按照MAX_SIZE_ARRAY来进行扩容

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

我们在调用这个接口的时候,这些方法可以直接被使用.


     

Java对象的比较

       1.基本类型的比较

在Java中,基本数据类型可以直接进行比较

运行结果:

       

         2.对象比较的问题

从编译结果来看,Java中引用类型的变量不能直接使用 > 或者 <的方式进行比较,那 == 为什么可以呢?

因为:用户实现自定义类型,都默认继承自Object类,而Object类提供了equal方法,而==默认情况下调用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用的对象,而是直接比较引用变量的地址.

        3.对象比较的方法

        1.重写equals方法

在上面创建的两个Student对象,他们的名字和年龄都相同,意味着他俩是同一个Student.而在重写equals方法中只要年龄和名字相同就返回true.

equal只能按照相等进行比较,本能按照大于 , 小于的方式进行比较.

       

         2.基于Comparable接口类的比较

如果想按照大小的方式进行比较,在自定义类时,实现Comparble接口即可,然后重写compareTo方法.但这种方法还是存在缺陷,就像上面代码显示一样,只能按照年龄进行比较,不能按照其他变量进行比较.

       

        3.基于比较器的比较

代码表示: 

我们想用什么变量比较就实现Comparble接口即可,然后重写compareTo方法.


Top- k问题

TOP-K问题:即求数据集合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大.

思路:

1. 用数据集合中的前 k 个元素来建堆

        ● 前k个最大元素 :建小根堆

        ●前k个最小元素 : 建大根堆

2. 用剩余的N-k个元素和堆顶元素进行比较 , 不满足则替换堆顶元素 ,

将剩余的N-k 个元素依次和堆顶元素比较 , 堆中剩余的元素就是前K个最大的或者最小的元素.

用比较器构造大根堆和小根堆

代码实现前k个最大元素 :

java中默认使用的是小根堆,在求前k个最大元素的时候可以不使用比较器建小根堆

 public int[] maxK(int[] arr,int k) {
        int ret[] = new int[k];
        if(arr == null || k == 0) {
            return ret;
        }
        //建立K个元素的小根堆
        Queue<Integer> minHeap = new PriorityQueue<>(k);
        //遍历数组的前K个,放到堆中
        for (int i = 0; i < k; i++) {
            minHeap.offer(arr[i]);
        }
        //遍历剩下的k-1个,和堆顶元素比较
        // 堆顶元素小的时候就出堆
        for (int i = k; i < arr.length; i++) {
            int val = minHeap.peek();
            if(val < arr[i]) {
                minHeap.poll();
                minHeap.offer(arr[i]);
            }
        }
        for (int i = 0; i < k; i++) {
            ret[i] = minHeap.poll();
        }
        return ret;
    }

代码实现前k个最小元素 :

public class TestDemo<E> {
        //求最小的K个数,通过比较器创建大根堆
        public  int[] smallestK(int[] array, int k) {
            if (k <= 0) {
                return new int[k];
            }
            GreaterIntComp greaterCmp = new GreaterIntComp();
            PriorityQueue<Integer> maxHeap = new PriorityQueue<>(greaterCmp);
            //先将前K个元素,创建大根堆
            for (int i = 0; i < k; i++) {
                maxHeap.offer(array[i]);
            }
//从第K+1个元素开始,每次和堆顶元素比较
            for (int i = k; i < array.length; i++) {
                int top = maxHeap.peek();
                if (array[i] < top) {
                    maxHeap.poll();
                    maxHeap.offer(array[i]);
                }
            }
//取出前K个
            int[] ret = new int[k];
            for (int i = 0; i < k; i++) {
                int val = maxHeap.poll();
                ret[i] = val;
            }
            return ret;
        }
    }
}

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

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

相关文章

asp.net core openxml读取word内容

安装包 OpenXMLSDK-MOT System.IO.Packaging 编写代码测试 using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wordprocessing; using System; using System.Linq; using System.Text;namespace WordReader {internal class Program{static void Main(…

【Python从入门到进阶】37、selenium关于phantomjs的基本使用

接上篇《36、Selenium 动作交互》 上一篇我们介绍了selenium操作网页的动作内容。本篇我们来学习有关phantomjs的相关知识。 一、selenium的缺点 在介绍PhantomJS之前&#xff0c;让我们先讨论一下直接使用Selenium的一些缺点。 1、显示浏览器窗口&#xff1a;Selenium通常需…

管理类联考——数学——汇总篇——知识点突破——几何——平面几何——记忆

文章目录 整体记忆宫殿角度/分类/串联线——从小到大角度/分类/串联线2——求长度&#xff0c;面积&#xff0c;角度 局部数字编码口诀法五大模型/共角定理、风筝模型、蝴蝶模型 转化图像法特点法公式推导法&#xff1a;公式推导掌握数学公式射影定理共角定理燕尾定理蝴蝶定理/…

Mysql高级——数据库设计规范(1)

数据库设计规范 1. 为什么需要数据库设计 数据库设计是为了有效地组织和管理数据。它是一个重要的步骤&#xff0c;用于创建一个结构良好、高效和可靠的数据库系统。以下是一些需要数据库设计的原因&#xff1a; 数据组织&#xff1a;数据库设计帮助我们将数据按照一定的结构…

Android 引入FFmpeg

1.安装 CMake 首先&#xff0c;需要下载 CMake 相关工具&#xff0c;在 Android Studio 中依次点击 Tools->SDK Manager->SDK Tools &#xff0c;然后勾选 CMake : CMake 构建工具 NDK : NDK 环境 最后依次点击 OK->OK->Finish &#xff0c;开始下载&#xff0…

科技资讯|苹果获批手机“Touch Bar”新专利,苹果Find My依旧火爆

根据美国商标和专利局&#xff08;USPTO&#xff09;公示的清单&#xff0c;苹果获得了一项 iPhone 专利&#xff0c;在机身侧面装上一个“Touch Bar”&#xff0c;用于显示电量等信息&#xff0c;并支持相关的交互操作。 这项专利最早于 2011 年提交&#xff0c;并于 2014 年…

OJ练习第180题——颠倒二进制位

颠倒二进制位 力扣链接&#xff1a;190. 颠倒二进制位 题目描述 颠倒给定的 32 位无符号整数的二进制位。 提示&#xff1a; 请注意&#xff0c;在某些语言&#xff08;如 Java&#xff09;中&#xff0c;没有无符号整数类型。在这种情况下&#xff0c;输入和输出都将被指…

FPGA 图像缩放 千兆网 UDP 网络视频传输,基于B50610 PHY实现,提供工程和QT上位机源码加技术支持

目录 1、前言版本更新说明免责声明 2、相关方案推荐UDP视频传输--无缩放FPGA图像缩放方案我这里已有的以太网方案 3、设计思路框架视频源选择IT6802解码芯片配置及采集动态彩条跨时钟FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择 UDP协议栈UDP视频数据组包UDP…

Spring | 异常处理最佳实践

引言 在快速迭代和持续交付的今天&#xff0c;软件的健壮性、可靠性和用户体验已经成为区别成功与否的关键因素。特别是在Spring框架中&#xff0c;由于其广泛的应用和丰富的功能&#xff0c;如何优雅地处理异常就显得尤为重要。本文旨在探讨在Spring中如何更加高效、准确和优…

【设计模式】组合模式

文章目录 1.组合模式定义2.组合模式的结构2.1. 安全式组合模式的结构2.2.透明式组合模式的结构 3.组合模式实战案例3.1.场景说明3.2.关系类图3.3.代码实现 4.组合模式优缺点5.组合模式适用场景6.组合模式总结 主页传送门&#xff1a;&#x1f481; 传送 1.组合模式定义 组合模式…

Spring面试题8:面试官:说一说Spring的BeanFactory

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:说一说Spring的BeanFactory Spring的BeanFactory是Spring框架的核心容器,负责管理和创建Bean对象。它是一个工厂类,用于实例化、配置和管理Bean的…

忽视日志吃大亏,手把手教你玩转 SpringBoot 日志

一、日志重要吗 程序中的日志重要吗&#xff1f; 在回答这个问题前&#xff0c;笔者先说个事例&#xff1a; ❝ 笔者印象尤深的就是去年某个同事&#xff0c;收到了客户反馈的紧急bug。尽管申请到了日志文件&#xff0c;但因为很多关键步骤没有打印日志&#xff0c;导致排查进…

基于springboot+vue的车辆管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

专业排版软件InDesign 2023下载 InDesign mac中文功能

InDesign 2023 mac是一款专业排版软件&#xff0c;适用于Windows和macOS平台。它可以帮助用户创建、设计和排版各种印刷品和数字出版物&#xff0c;如杂志、书籍、报纸、广告、海报、手册、电子书等。 InDesign 2023 mac软件特点 多种页面布局&#xff1a;支持多种页面布局&…

名义实际GDP-各地区-原始和结果(2000-2022年)

一、数据介绍 数据名称&#xff1a;名义、实际GDP-各地区-原始和结果 数据年份&#xff1a;2000-2022年 计算公式&#xff1a;实际GDP 名义GDP / GDP折算指数 数据基期&#xff1a;2000年 数据整理&#xff1a;自主整理 二、数据用途 数据用途 文献依据 经济发展水平 …

如何在.NET电子表格应用程序中创建流程图

前言 流程图是一种常用的图形化工具&#xff0c;用于展示过程中事件、决策和操作的顺序和关系。它通过使用不同形状的图标和箭头线条&#xff0c;将任务和步骤按照特定的顺序连接起来&#xff0c;以便清晰地表示一个过程的执行流程。 在企业环境中&#xff0c;高管和经理利用…

区间重叠问题

区间未重叠数量计算&#xff1a; class Solution {public int findMinArrowShots(int[][] points) {//需要用第一种比较器&#xff1f;第二种会报错&#xff0c;在涉及数的大小边界的时候Arrays.sort(points,(a, b) -> Integer.compare(a[0], b[0]));//(a, b) -> Intege…

【算法思想-排序】根据另一个数组次序排序 - 力扣 1122 题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

员工执行力差,80%是领导的问题

作者| Mr.K 编辑| Emma 来源| 技术领导力(ID&#xff1a;jishulingdaoli) 读者小T是大厂P7&#xff0c;今年跳到一家行业独角兽公司&#xff0c;做项目经理。没想到&#xff0c;半年后他的领导Y总&#xff0c;在考核中给他的绩效打了D&#xff0c;主要原因是小T“项目按时完成…

大模型分布式训练策略:ZeRO、FSDP

文章目录 一、ZeRO&#xff08;零冗余优化器&#xff09;1.1 背景1.2 深度学习内存消耗分析1.3 主要方法1.3.1 ZeRO-DP优化模型状态内存1.3.2 ZeRO-R优化残余状态内存 1.4 总结1.5 官方视频&#xff1a;ZeRO & Fastest BERT&#xff0c;提高 DeepSpeed 深度学习训练的规模和…