【数据结构】大根堆和小根堆

news2024/9/23 0:41:33

image.png

大根堆实现逻辑

从整棵树的最后一颗子树开始调整,每次都让根节点和左右孩子去比较,如果根节点比左右孩子的最大值要小,那么就将这两个值进行交换,然后此时这颗子树变成了大根堆,再看下一颗树
image.png|570
然后对下一颗树进行相同的处理方法,后面的子树依次交换:
image.png|520


当每棵子树都是大根堆的情况下,那么这棵树也就是大根堆了

每一次交换的步骤为:

  1. 从最后一棵树开始调整
  2. 左右孩子的最大值和根节点进行比较,如果大于根节点,就交换

遇到的主要问题

第一组根节点和左孩子节点的值在哪


  1. 既然调整要从最后一棵子树的根节点开始,那如何确定最后一棵子树的根节点在哪?
  • 把最后一棵子树的根节点记作 p(parent),左节点的值记作 c(child)
  • 由于堆是由数组实现的,我们最初在创建堆的时候,每一个值都有一个下标,并且是按照层序排序的方式进行完全二叉树的构建,所以原数组的最后一个元素,也就是下标为数组长度-1 (len - 1) 的元素就是最后一个叶子节点,既然知道了最后一棵子树根节点的左孩子节点,那么就可以推出根节点的位置了,p 的下标为:(len-1-1)/2
    image.png|428

后续根节点和左孩子节点的值如何确定

  1. 最后一棵子树的根节点和孩子找到了,并且交换完成了,那怎么确定下一棵子树中要交换的一组根节点和左孩子节点的值呢?
  • 之后的根节点 p 只需要在每一交换完成之后进行 p-- 的操作就可以定位到下一棵需要交换的子树的根节点位置了,最后一个 p 的下标为 0
  • 而孩子节点 c 则需要通过根节点的位置进行推导,c 的下标为:2*p+1
    image.png

右孩子值更大怎么办

  1. 把左孩子节点记作 c(child),每次都是 c(child) 与根节点 p(parent) 进行交换,那要是右孩子节点比左孩子节点要大呢?

因为我们每次都是对左右孩子的最大值与根节点进行交换,所以我们要时刻保证 c(child) 代表的是左右孩子中更大的那个。
由于 c(child) 最先是指向左孩子的,

  1. 若左孩子节点 > 右孩子节点,继续进行交换
  2. 若左孩子节点 < 右孩子结点,则 child++,让 child 代表右孩子

这一切都是发生在每一次准备进行交换的前一刻,为将要交换的 childparent 提供准确的数据


什么时候一轮交换结束

  1. 在每一次进行交换操作的时候,什么时候代表交换结束呢?

image.png


如何进行交换操作

  1. 需要交换的元素知道了,交换开始的条件知道了,交换的结束条件也知道了,那该如何进行交换操作呢?

此时我们创建一个 swap(int i, int j) 交换方法:

  1. 创建一个 tmp 整型变量,用来存放 elem[i] 的值
  2. 再将 elem[i] 的值赋给 elem[i]
  3. 最后将 tmp 中存放的 elem[i] 的值赋给 elem[j]
    image.png|539

大根堆完整代码

public void creatHeap(){  
    for (int parent = (usedSize-1-1)/2; parent >= 0 ; parent--) {  
        shiftDown2(parent,usedSize);  
    }
}  
  
public void swap(int i, int j) {  
    int tmp = elem[i];  
    elem[i] = elem[j];  
    elem[j] = tmp;  
}  
  
  
public void shiftDown(int parent, int end) {  
    //parent的值是作为参数传进来的,我们需要用parent的下标算出child的下标  
    int child = parent*2+1;  
    
    //每一轮交换进行的条件  
    while(child < end){  
        //右节点比左节点大的时候,但前提是右节点必须存在  
        if(child+1 < end && elem[child+1] > elem[child]){  
            child++;  
        }        
    	//调整过后,child代表的就永远都是更大的子节点  
        
        //当子节点比根节点大时,进行交换  
        if(elem[child] > elem[parent]){  
            swap(parent,child);  
            parent = child;  
            child = 2*parent+1;  
        }else {  
            //若子节点小于根节点,则跳出循环  
            break;  
        }    
    }
}

观察调试结果,可发现已变成大根堆
在这里插入图片描述

小根堆的实现

小根堆的实现只需要在大根堆实现的基础上将

  1. child 的指向改为指向更小的那个节点:
    if (child + 1 < end && elem[child + 1] < elem[child]) {child++;}
  2. parentchild 交换的条件改为 if (elem[child] < elem[parent])

小根堆的代码与大根堆相似度高达 99%,只需要将 shiftDown 方法中的第 7 和 13 行进行微微调整即可

public void shiftDown2(int parent, int end) {  
    //parent的值是作为参数传进来的,我们需要用parent的下标算出child的下标  
    int child = parent * 2 + 1;  
    //一轮交换进行的条件  
    while (child < end) {  
        //右节点比左节点大的时候,但前提是右节点必须存在  
        if (child + 1 < end && elem[child + 1] < elem[child]) {  
            child++;  
        }        
        //调整过后,child代表的就永远都是更小的子节点  
        
        //当子节点比根节点小时,进行交换  
        if (elem[child] < elem[parent]) {  
            swap(parent, child);  
            parent = child;  
            child = 2 * parent + 1;  
        } else {  
            //若子节点大于根节点,则跳出循环  
            break;  
        }   
    }
}

观察调试结果,可发现已变成小根堆
在这里插入图片描述

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

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

相关文章

【大模型框架】【基本结构】transformer

论文地址:https://arxiv.org/pdf/1706.03762 1. 整体结构 2. 内部结构 3. 公式 Transformer工作原理四部曲:Embedding(向量化)、Attention(注意力机制)、MLPs(多层感知机)和Unembedding(模型输出)。

域名过期了网站还能访问吗?怎么查询域名过期?

在当今数字化的时代&#xff0c;网站已经成为企业、个人展示形象和提供服务的重要窗口。而域名作为网站的标识&#xff0c;其重要性不言而喻。然而&#xff0c;域名是有一定有效期的&#xff0c;那么当域名过期了&#xff0c;网站还能访问吗&#xff1f;又该如何查询域名的过期…

Mysql的事务隔离级别实现原理

一、事务隔离级别 mysql支持四种事务隔离级别&#xff1a; 读未提交&#xff1a;一个事务可以读取到另一个事务还未提交的数据&#xff1b;读已提交&#xff1a;一个事务可以读取到另一个事务已经提交的数据&#xff1b;可重复读&#xff1a;同一个事务中&#xff0c;无论读取…

【C语言】数组和函数实践:扫雷游戏

扫雷游戏 1. 扫雷游戏分析和设计1.1 扫雷游戏的功能说明1.2 游戏的分析和设计1.2.1 数据结构的分析1.2.2 ⽂件结构设计 2. 扫雷游戏的代码实现&#xff08;1&#xff09;菜单menu函数&#xff08;2&#xff09;设计main函数&#xff08;3&#xff09;设计game函数&#xff08;4…

免费分享:2013中国沙漠(沙地)分布数据集(附下载方法)

沙漠是指地面完全被沙所覆盖、植物非常稀少、雨水稀少、空气干燥的荒芜地区。沙漠亦作“沙幕”&#xff0c;干旱缺水&#xff0c;植物稀少的地区&#xff0c;通常为风成地貌。中国是世界上沙漠面积较大、分布较广、沙漠化危害严重的国家之一&#xff0c;因此我国十分注重防沙治…

发布Meta Segment Anything Model 2 (SAM 2):开启图像和视频分割的新时代

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

DiffusionModel-latent diffusion,VAE,U-Net,Text-encoder

Diffusers StableDdiffusion Latent Diffusion 稳定扩散&#xff08;Stable Diffusion&#xff09;模型中使用的三个关键组件&#xff1a;自编码器&#xff08;VAE&#xff09;、U-Net和文本编码器&#xff08;Text-encoder&#xff09; 由于潜在扩散模型的U-Net操作在低维空…

掌握FluentResults:.NET中优雅处理结果与错误

在.NET开发中&#xff0c;结果和错误处理是构建健壯应用程序的关键部分。FluentResults是一个.NET库&#xff0c;它提供了一种优雅的方式来处理操作结果和错误。它允许开发者以声明性和链式调用的方式构建结果对象&#xff0c;使得代码更加清晰和易于维护。本文将介绍FluentRes…

云原生大数据平台KDP,实战疑难问题解答

智领云的KDP&#xff08;Kubernetes Data Platform&#xff09;是一款自主研发的容器化云原生大数据平台&#xff0c;它是市场上首个能够完全在Kubernetes上部署的大数据平台。KDP深度整合了云原生架构的优势&#xff0c;解决了传统Hadoop大数据平台在架构限制、部署、运维、运…

ctfshow~菜狗杯 flag一分为二

第一步&#xff1a;解压附件得到miku.png文件 第二步&#xff1a;修改图片高度出现一半的flag 第三步&#xff1a;使用盲水印提取工具得到另一半工具 ctfshow{FirstPRTSecondPrTMikumiku~}

认识systemctl

1: 概述 systemctl命令可以帮助systemd管理和维护所有服务,系统启动完成后,systemctl命令会向systemd发送消息进行服务启动和停止等操作,想知道为什么systemctl命令可以向systemd传递消息吗,其实它是通过一个叫D_Bus(desktop bus)桌面总线的东西实现这一点,它可以并行的处理多…

劝你先别更新!!最新Stable Diffusion WebUI 1.10已来!WebUI终于支持SD3大模型了!你跑起来了么?

你的SD3大模型在SD WebUI1.10.0中跑起来了么&#xff1f; 今天发现Stable Diffusion WebUI于昨日推出了最新SD WebUI1.10.0 版本。令人比较兴奋的是该版本支持了SD3大模型&#xff0c;同时也新增了DDIM CFG采样器。主要更新内容如下&#xff1a; 最新版本地址&#xff1a; 更新…

跨境电商TikTok达人合作策略:驱动口碑传播,助力经济增长

通过与TikTok达人的深度合作&#xff0c;跨境电商不仅能够有效提升品牌曝光度和销售额&#xff0c;还能激发用户的口碑传播&#xff0c;形成强大的“口碑经济”效应。本文Nox聚星将和大家分析这种合作模式如何引发口碑经济效应&#xff0c;并探讨如何通过优化合作策略&#xff…

Python酷库之旅-第三方库Pandas(058)

目录 一、用法精讲 221、pandas.Series.interpolate方法 221-1、语法 221-2、参数 221-3、功能 221-4、返回值 221-5、说明 221-6、用法 221-6-1、数据准备 221-6-2、代码示例 221-6-3、结果输出 222、pandas.Series.isna方法 222-1、语法 222-2、参数 222-3、功…

JAVA的String类的contains方法,Indexof方法不使用KMP算法

今天做力扣的一道题目&#xff0c;在一个字符串中找出字符串的时候&#xff0c;想到了JAVA有一个contains方法&#xff0c;于是我去看了一下源码&#xff0c;发现他就是简单地调用了一下java的indexof方法&#xff0c; 然后我又去看了Indexof的源码&#xff0c;发现他就是简单的…

深入探讨C++编译期多态:提高效率与安全性

目录 一、引言 二、编译期多态技术详解 函数重载&#xff08;Function Overloading&#xff09; 运算符重载&#xff08;Operator Overloading&#xff09; 模板元编程&#xff08;Template Metaprogramming&#xff09; 使用std::enable_if实现条件模板特化 使用if con…

让我们逐行重现 GPT-2:第 1 部分

欢迎来到雲闪世界。Andrej Karpathy 是人工智能 (AI) 领域的顶尖研究人员之一。他是 OpenAI 的创始成员之一&#xff0c;曾领导特斯拉的 AI 部门&#xff0c;目前仍处于 AI 社区的前沿。 在第一部分中&#xff0c;我们重点介绍如何实现 GPT-2 的架构。虽然 GPT-2 于 2018 年由 …

Gradle下载的依赖jar包路径位置

Gradle依赖默认下载路径 Mac系统默认下载路径&#xff1a;C:/Users/(用户名)/.gradle/caches/modules-2/files-2.1 Windows系统默认下载路径&#xff1a;C:\Users(用户名).gradle\caches\modules-2\files-2.1 修改Gradle缓存文件夹路径 1. 配置环境变量 添加变量GRADLE_US…

elementUI,vue,前端判断时间是否有交集(重合)方法

分成三个部分 html※ 具体实现方法methods帮助理解逻辑图&#xff1a;![smallredBook&#xff1a;灵魂画手&#xff0c;业余爱好支持支持](https://i-blog.csdnimg.cn/direct/665950ee60964ef8912ce4f1a98dcc0e.jpeg#pic_center) 简化&#xff1a;由上面的逻辑反推[^1] html &…