数据结构堆介绍,图文详解分析——Java/Kotlin双版本代码

news2025/1/22 16:13:46

堆介绍

堆是一种特殊的树结构。根据根节点的值与子节点值的大小关系,堆又分为最大堆和最小堆。

最大堆:每个节点的值总是大于或者等于其任意子节点的值。所以最大堆中根节点即为最大值。

最小堆:每个节点的值总是小于或者等于其任意子节点的值。所以最小堆中根节点即为最小值。

堆的特点是最大值或最小值位于堆的顶部,只需要O(1)的时间就可以求出一个数据集合中的最大值或最小值,同时在堆中添加或删除元素的时间复杂度都是O(logn)。因此堆通常用来求一个动态的集合中的k个最大值或者最小值。

在这里插入图片描述

堆实现

堆通常使用完全二叉树实现,在完全二叉树中,除了最底层之外其他层均为填满,最底层则是从左到右的顺序排列。所以完全二叉树就可以使用数组进行实现,因此堆也可以使用数组进行实现。

将堆的每一层从左到右的节点按照0,1,2的顺序进行排列。编号0放到数组0的位置,编号1放到数组1的位置,就可以将堆放到数组中去。比如上述最大堆和最小堆,可以使用下方的数据结构进行表示

在这里插入图片描述

用数组表示堆**,如果一个元素在数组中的下表是i,则其在堆中的父节点在数组中的坐标为(i-1)/2,而它的左右子节点在数组中的下标分别为2i+12i+2**。

堆的增删

此处使用最大堆进行解释,最小堆和最大堆理论都一样的

最大堆添加节点

  1. 从上到下,从左右到找到第一个空缺的位置,将新的节点添加到空缺的位置上。
  2. 对比新节点的值和父节点的值,如果新节点的值比父节点的值大,则交换新节点和父节点的值。
  3. 重复步骤2,直到新节点的值大于或者等于父节点的值或者已经到达根节点。

如下,在之前最大堆上添加新元素95,图解过程如下:

在这里插入图片描述

最大堆删除节点

通常只删除堆顶部节点,删除步骤如下:

  1. 删除最大堆顶部节点
  2. 将堆最底部最右边的节点移到堆的顶部
  3. 如果存在左右子节点的值大于顶部节点的值,则它和左右子节点值中的最大值进行交换
  4. 重复上述步骤,直到该节点的值大于或等于其左右子节点的值,或者抵达最后一层。

如下,删除最大堆元素95,图解过程如下:

时间复杂度

基于上述的描述,从堆里面获取最大值或者最小值的时间复杂度为O(1)

对堆进行增减或者删除的时间复杂度为树高O(logn)

堆的应用

java使用PriorityQueue实现了堆数据结构。PriorityQueue默认的情况下是一个最小堆,如果要使用最大堆则需要自己传入Comparator。

PriorityQueue实现了Queue接口,其常用的函数如下所示:

操作抛异常不抛异常
插入新的元素add(e)offer(e)
删除堆顶元素removepoll
返回堆顶元素elementpeek

通常使用堆求取一个动态数据集合中最大或者最小的k个元素。通常,使用最小堆求取集合中k个最大的元素,使用最大堆求取集合中k个最小的元素

题目:设计一个数据结构,它每次从一个数据流中读取一个数字,并得出数据流已经读出的数字中第k(k>1)大的数字。该数据结构有一个构造器,构造器接受一个参数k(整数),另外接收一个数组(假设数组长度大于k)。还有一个函数add用来动态的添加数字,并返回此时读取中的第k大的值。

列如:当k=2,nums数组为[4,3,5,6],调用构造函数初始化之后,第一次调用add传入7此时应返回6,再次调用add传入8此时应该返回7。

分析:数据流相关的特点是输入的数据是动态添加且无限的。所以我们需要一个数据结构每次只保存之前k大的几个值,每次add的时候,只需要判断保存的值里面的最小值是否小于add的值,如果小于则替换即可。所以这里可以使用最小堆。

代码参考

kotlin 版本

class HeapTest(val k: Int, num: Array<Int>) {
    private val minHeap = PriorityQueue<Int>()

    init {
        for (i in num) {
            add(i)
        }
    }
    
    fun add(e: Int): Int {
        if (minHeap.size < k) {
            minHeap.offer(e)
        } else if (minHeap.peek() < e) {
            minHeap.poll()
            minHeap.offer(e)
        }
        return minHeap.peek()
    }
}

测试

    val heapTest = HeapTest(3, arrayOf(4, 5, 8, 2))
    println(heapTest.add(3))
    println(heapTest.add(5))
    //结果
    第一次调用 传入3  返回4
    第二次调用 传入5  返回5

java 版本

public class HeapTestJava {
    private final PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    private final int k;

    public HeapTestJava(int k, int[] num) {
        this.k = k;
        for (int i : num) {
            add(i);
        }
    }

    public int add(int v) {
        if (minHeap.size() < k) {
            minHeap.offer(v);
        } else if (v > minHeap.peek()) {
            minHeap.poll();
            minHeap.offer(v);
        }
        return minHeap.peek();
    }
}

🙆‍♀️。欢迎技术探讨噢!

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

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

相关文章

第六章课后题(LSTM | GRU)

目录习题6-3 当使用公式(6.50)作为循环神经网络得状态更新公式时&#xff0c;分析其可能存在梯度爆炸的原因并给出解决办法.习题6-4 推导LSTM网络中参数的梯度&#xff0c;并分析其避免梯度消失的效果​编辑习题6-5 推导GRU网络中参数的梯度&#xff0c;并分析其避免梯度消失的…

集合框架----源码解读Vector篇

1.vector官方简绍 Vector类实现了一个可增长的对象数组。与数组一样&#xff0c;它包含可以使用整数索引访问的组件。但是&#xff0c;Vector的大小可以根据需要增加或缩小&#xff0c;以适应在创建Vector之后添加和删除项。 每个向量都试图通过维护一个容量和一个capacityIncr…

C#设计模式详解(2)——Factory Method(工厂方法)

文章目录C#设计模式详解(2)——Factory Method&#xff08;工厂方法&#xff09;工厂方法模式1.1 概念1.2 意图1.3 问题1.4 解决方案1.5 工厂方法模式结构1.6 案例代码1.7 游戏开发中的应用C#设计模式详解(2)——Factory Method&#xff08;工厂方法&#xff09; 工厂方法模式…

领悟《信号与系统》之 非周期信号的傅里叶变换

非周期信号的傅里叶变换一、非周期信号的傅里叶变换二、 典型信号的傅立叶变换1.单边指数信号2.偶双边指数3. 矩阵脉冲信号4. 奇双边指数5. 符号函数6. 冲激信号7. 阶跃信号三、常用傅里叶变换表这里记录的信号都是非周期信号的傅里叶变化&#xff0c;频谱变换的特点就是&#…

【计算机网络】数据链路层:使用广播信道的数据链路层(1)

局域网的数据链路层 局域网特点&#xff1a;网络为一个单位所拥有&#xff0c;地理范围和站点数目均有限。 地理范围和站点数目均有限。 局域网优点&#xff1a; 具有广播功能&#xff0c;从一个站点可以很方便地访问全网。 便于系统的拓展和演变&#xff0c;各设备的位置…

Discourse 论坛激活邮件问题

根据 Discourse 的官方推荐&#xff0c;我们使用的是 MailGun 的服务。 在大部分情况下都没有问题&#xff0c;但是在一些特定的邮件地址&#xff0c;例如 iCloud&#xff0c;我们在发送激活邮件的时候有提示为&#xff1a; "message": "5.5.1 Error: need MA…

实验:温湿度数据oled显示

OK,本次介绍一个oled实验 本来只想做oled实验的 后面想想这个实验太简单 就加上了温湿度传感器 oled可以打印英文和数字,比如用display.println(“Hello World!”)就可以了 如果打印汉字就比较复杂了 需要相应的软件,生成编码 然后一个字一个字打印 不过只要汉字不…

【数据结构】树——二叉树

1.树的介绍以及树的基本概念和性质 2.二叉树介绍以及二叉树的性质 3.二叉树的构建&#xff1a;穷举创建&#xff0c;递归创建 4.二叉树的基本操作 之前我们介绍了顺序表&#xff0c;链表&#xff0c;以及栈和队列&#xff0c;这几种数据结构都属于线性结构&#xff0c;而我们接…

GreenPlum/PostGreSQL表锁处理

GreenPlum/PostGreSQL表锁处理 数据库中遇到表锁的情况&#xff0c;可以通过select * from pg_stat_activity;查看表锁的进程及进程ID&#xff0c;从而取消进程&#xff0c;解锁。 一、模拟表锁 1.1 模拟表数据 创建lock_test表&#xff0c;并随意插入一条数据&#xff0c;…

Oracle自治事务示例演示

自治事务 自治事务&#xff08;Pragma autonomous_transaction&#xff09;&#xff1a;是PL/SQL块中的一个单独事务&#xff0c;与调用或触发自己的事务之间互不干扰&#xff0c;自己commit和rollback不会影响其他事务&#xff0c;也不会被其他事务所影响。 通俗的讲&#xff…

【Android App】在线语音识别功能实现(使用云知声平台与WebSocket 超详细 附源码)

需要源码和相关资源请点赞关注收藏后评论区留下QQ~~~ 一、在线语音识别 云知声的语音识别同样采用WebSocket接口&#xff0c;待识别的音频流支持MP3和PCM两种格式&#xff0c;对于在线语音识别来说&#xff0c;云知声使用JSON串封装报文&#xff0c;待识别的音频以二进制形式发…

webpack打包vue文件+gulp打包sass文件

webpack打包vue文件 1,下载依赖 npm i vue-loader npm i webpack-cli2&#xff0c;编写webpack配置文件 /*** 关于webpack的配置文件*/const path require(path)const { VueLoaderPlugin } require(vue-loader)const glob require(glob) // node自带的读取文件的库 /*** …

会多门编程语言的你,最推荐哪3-5门语言?

如果你还想在编程的路上继续提高&#xff0c;那我建议你至少学习4种编程语言。可用的编程语言有很多&#xff0c;所以选择一种感兴趣的学习就可以了。我这么建议的原因是&#xff0c;要掌握编程&#xff0c;建立信心&#xff0c;提高能力&#xff0c;最简单的办法就是学习多种编…

浅析工作流调度器Azkaban

title: Azkaban系列 第一章 概述 1.1 为什么需要工作流调度器 1、一个完整的数据分析系统通常都是由大量任务单元组成&#xff1a; shell 脚本程序&#xff0c;java 程序&#xff0c;mapreduce 程序、hive 脚本等 2、各任务单元之间存在时间先后及前后依赖关系 3、为了很好地…

TIA西门子博途V18安装教程及注意事项

TIA西门子博途V18安装教程及注意事项 前提条件: TIA Portal V18需要.Net Framework 3.5环境,所以在安装TIA V18之前要先安装它。大家可以在控制面板中的程序和功能中检查是否已经安装,如果没有,可以参考以下步骤自行安装: 操作系统&#x

jsp旅行网系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 旅行网系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql&#xff0c;使用java语…

[附源码]Python计算机毕业设计房屋租赁系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

2022级浙大MEM录取经验过程分享——有需求就要去匹配

我是2022 级 浙大MEM 新录取的考生&#xff0c;去年联考初试取得了213 分的成绩&#xff0c;综合拿到了148分&#xff0c;去年的提面中也拿到了优秀资格&#xff0c;在备考的过程中自己的一些心得体会和经验分享给大家&#xff0c;希望能够有所帮助。我的本科其实比较普通&…

python循环中的continue和break

目录 一.python中的continue 案例1 结果是 注意 案例2 结果是 二.python中的break 案例1 结果是 注意 案例2 结果是 三. python中continue和break的总结 一.python中的continue continue关键字用于:中断本次循环&#xff0c;直接进入下一次循环 continue可以用于:fo…

2.1.2 运算放大器的组成与分类、运算放大器的发展历程

笔者电子信息专业硕士毕业&#xff0c;获得过多次电子设计大赛、大学生智能车、数学建模国奖&#xff0c;现就职于南京某半导体芯片公司&#xff0c;从事硬件研发&#xff0c;电路设计研究。对于学电子的小伙伴&#xff0c;深知入门的不易&#xff0c;特开次博客交流分享经验&a…