左式堆的合并

2023-11-14

二叉堆对于合并操作是困难的,因为需要把一个数组拷贝到另一个数组。

左式堆可以高效的地支持合并操作, 左式堆与二叉树之间唯一区别是,左式堆不是平衡的,可能非常趋向不平衡。

// 左式堆的结构
typedef struct TreeNode {
    element_t element;
    struct TreeNode *left;
    struct TreeNode *right;
    int npl;
} LeftistHeap;

任一节点X的零路径长Npl(X)定义为从X到一个没有两个儿子的节点的最短路径。
左式堆的性质:对于堆中每一个节点X,左儿子的零路径长至少与右儿子的零路径长一样大,即

X->left->npl >= X->right->npl;

可以这样理解

// 求Npl
int Npl(LeftistHeap X) { 
    if (!X) // 节点为NULL时,Npl为-1;
        return -1;
    else if (X->left && X->right) // 节点左右儿子都存在时,返回右儿子的零路径(根据性质)
        return X->right->npl + 1;
    else 
        return X->right->npl; // 只有左儿子或者没有左右儿子时返回右儿子的零路径
}

有一个左式树的定理

在右路径上有r个节点的左式树必然有 2r1 个节点

首先右路径是这棵树的最右边的那一条路径(不是右子树的节点,摔,在这里犯混了),我们用递归的思想去验证,
考虑最右边的节点,根据性质一棵树的右节点必定有左节点与之匹配,所以这棵树至少有 r 个(可能左兄弟还有左儿子)左儿子,
所以树上至少有 2r1 个节点。

现在开始思考左式堆的合并操作了,那么肯定就要用到它的性质

X->left->npl >= X->right->npl;

根据上面的定理,一个含有n个节点的左式树有一条右路径至多含有 log(n+1) 个节点,这样可以确保树的右路径的长度,所以对每次合并操作都是对树的右节点进行操作,朝着右路径进行,总结起来就是两棵树先从树根开始比较,值更大的节点成为值更小的节点的右儿子,同时满足小根堆的特点(儿子比父节点的值更大,反之则反),终止条件是一棵树到达了两棵树的右路径的最后一个节点,中间过程有左儿子npl小于右儿子npl的时候,交换左右儿子。

// 合并左式堆的驱动例程(就是控制该把哪棵树合并到另外一棵树下)

LeftistHeap Merge(LeftistHeap h1, LeftistHeap h2) {
    if (!h1) // 当一个树为空树时返回另外一棵树
        return h2;
    if (!h2)
        return h1;
    if (h1->element < h2->element) // 把值大的节点所在的树合并到值小的节点所在树
        return merge(h1, h2);
    else 
        return merge(h2, h1);
}

// 合并的实际例程
static LeftistHeap merge(LeftistHeap h1, LeftistHeap h2) {
    if (!h1->left) 
        h1->left = h2; // 为满足左式堆性质
    else {
        h1->right = Merge(h1->right, h2); // 朝值小的节点所在树的右路径方向进行
        if (h1->left->npl < h1->right->npl) // 当左子树的npl小于右子树的npl时,交换左右儿子
            swap(h1->left, h1->right);
        h1->npl = h1->right->npl + 1;   // 更新当前节点的npl
    }
    return h1;
}

左式堆的插入操作为创建一个节点即只有一个根节点的树与需要插入的树进行Merge操作。
删除操作,最小(大)的元素处在树根的位置,只需要把根节点删除就可以,然后对左右子树进行Merge操作。

// 前几天看到网上的很多博客都一个样子,定下心来自己理解后,写下这篇博客, 没有把所有代码都贴上来,把主要的思想和部分代码写在这里。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

左式堆的合并 的相关文章

  • 以太坊合并升级的全面介绍

    以太坊主网即将通过称为 合并 的升级 从工作量证明转向权益证明共识机制 合并 Merge 是以太坊生态系统一系列主要升级的一部分 此外还有Surge Verge Purge以及Splurge 多次升级的目的是为了提高以太坊的可扩展性和能效
  • 两个单链表的合并(C语言实现)

    单链表的合并还是挺简单的 直接上代码吧 include
  • LeetCode——021

    21 Merge Two Sorted Lists My Submissions QuestionEditorial Solution Total Accepted 122136 Total Submissions 345783 Diffi
  • ECharts合并地图上的区域

    对于某些特定需求 官方下载的地图数据可能并不能完全满足 例如 要求显示中国地图 但需要将山东江苏和浙江这3个省合并起来 显示 东部区域 其他省份不变 于是就需要对官方提供的地图数据进行修改 一个思路是借助第三方工具 生成新区域的轮廓点 然后
  • 【Pandas 入门-2】增加,删除与合并数据 concat, merge

    文章目录 1 3 增加 删除与合并数据 1 3 1 增加数据 1 3 2 删除数据 1 3 3 合并数据 1 3 增加 删除与合并数据 1 3 1 增加数据 在原数据末尾增加一列时 语法为 df 新列名 某个值或某个元素个数与 DataFr
  • GridControl 列合并(自定义分组条件)

    说明 当前方式不提倡 最好还是使用 1 主从表 或 2 分组 一 数据源 DataTable dta new DataTable dta Columns Add A dta Columns Add B dta Columns Add C d
  • 快速解决Android编译报错 : Manifest merger failed with multiple errors, see logs

    编译项目的时候 遇到Android Manifest合并失败的情况就挺头疼的 Manifest merger failed with multiple errors see logs 直接运行项目 看不出来问题 以前都是通过 gradlew
  • ffmpeg合并两路rtmp流并推送

    ffmpeg实现两路流的覆盖 实现两路流的覆盖可以使用ffmpeg的overlay参数 将一路流覆盖到另外一路流之上 overlay参数简介 overlay x y 这里x和y表示距离左上角的坐标偏移 例子 ffmpeg i rtmp ip
  • git - 简明指南

    git 简明指南 助你入门 git 的简明指南 木有高深内容 安装 下载 git OSX 版 下载 git Windows 版 下载 git Linux 版 创建新仓库 创建新文件夹 打开 然后执行 git init 以创建新的 git 仓
  • Java使用POI操作Excel合并单元格

    合并单元格的方法 指定 4 个参数 起始行 结束行 起始列 结束列 然后这个区域将被合并 CellRangeAddress region new CellRangeAddress startRow endRow startCol endCo
  • 使用ffmpeg合并多个视频文件

    由于腾讯视频将一个视频分割成多个20M左右的小文件 所以必须合并起来成为一个完整视频文件 用什么工具来合并这些文件呢 想到了已经安装好的ffmpeg 开源免费 又是现成的 两种方法 方法1 直接写文件名 使用 来分割 ffmpeg i co
  • Pandas-连接合并函数merge()

    一 merge函数用途 pandas中的merge 函数类似于SQL中join的用法 可以将不同数据集依照某些字段 属性 进行合并操作 得到一个新的数据集 二 merge 函数的具体参数 用法 DataFrame1 merge DataFr
  • error: You have not concluded your merge (MERGE_HEAD exists).git拉取失败

    拉取git上的更新时出现错误如下 error You have not concluded your merge MERGE HEAD exists hint Please commit your changes before mergin
  • 合并两个有序单链表(Java)

    思想 准备两个链表l1和l2 判断是否有链表为空 如果l1为空 则不用比较直接返回l2 如果l1为空 则直接返回l2 比较l1和l2节点 选出最小的那个节点 将该节点设为合并后的链表的head 头 节点 同时将指向该节点的l1或l2后移 方
  • 源代码主干分支开发四大模式

    作者 张克强 作者微博 张克强 敏捷307 1 先锋主干多稳定分支 2 守护主干多先锋分支 3 主干无分支 4 守护主干单分支 一 先锋主干多稳定分支 得到一个稳定版本后 将此稳定版本放到一个新分支上 针对此稳定版本的修修补补就在这个分支上
  • 将2个链表交替合并成一个链表

    将带有头结点的2个线性单链表交替有规则的合并成为一个链表 今天做这个的时候 又犯了以前一个愚蠢的错误 对于有些代码 为了方便我就直接复制了 编译器查出来有错 我一直看不出来错误在哪里 那一块我直接就忽略了 代码不敢随便复制 我画个图我认为直
  • 字符串合并

    题目描述 详细描述 将输入的两个字符串合并 对合并后的字符串进行排序 要求为 下标为奇数的字符和下标为偶数的字符分别从小到大排序 这里的下标意思是字符在字符串中的位置 对排序后的字符串进行操作 如果字符为 0 9 或者 A F 或者 a f
  • mysql之union合并查询

    转载链接 http www cnblogs com zzwlovegfj archive 2012 06 23 2559592 html union 联合的意思 即把两次或多次查询结果合并起来 要求 两次查询的列数必须一致 推荐 列的类型可
  • 左式堆的合并

    二叉堆对于合并操作是困难的 因为需要把一个数组拷贝到另一个数组 左式堆可以高效的地支持合并操作 左式堆与二叉树之间唯一区别是 左式堆不是平衡的 可能非常趋向不平衡 左式堆的结构 typedef struct TreeNode element
  • 两个无序单链合并成一个有序单链表

    解题思路 两个无序链表先转换成两个有序单链表 两个有序单链表合并成一个有序单链表 代码 import java util 链表 class Node int val Node next public Node int val this va

随机推荐

  • 为什么需要单元测试?

    为什么需要单元测试 从产品角度而言 常规的功能测试 系统测试都是站在产品局部或全局功能进行测试 能够很好地与用户的需要相结合 但是缺乏了对产品研发细节 特别是代码细节的理解 从测试人员角度而言 功能测试和系统测试以及其他性能测试等等对测试人
  • Windows下忘记MySQL root密码解决方法

    Windows下忘记MySQL密码的解决办法网上好多好多 可是 我发现 如果采用Windows服务启动的时候 安装网上通过命令行修改root密码的方法行不通 经过实验 发现 Windows的服务运行的配置并不是在命令行下的配置 查看Wind
  • anaconda怎么运行python脚本_Anaconda运行python脚本 Anaconda方法教程

    你是否想了解Anaconda运行python脚本的操作 下面就是笔者带来的Anaconda运行python脚本的操作步骤 赶紧来看一下吧 相信对大家一定会有所帮助哦 Anaconda是使用 虚拟 环境里边运行Python 这样便于版本 包管
  • 面向对象的设计思想

    面向对象的设计思想 OO思想 Object Oriented 1 看到一个需求的时候不应该直接写代码 应该先考虑有哪些类 2 考虑类的时候 类一定是一类事务的描述 不能太局限 3 考虑类的时候需要考虑主要的类 也就是需要和业务 动作 事件紧
  • 声明指向unsigned int类型的对象的指针vptr_一步步分析:C语言如何面向对象编程...

    一 前言 在嵌入式开发中 C C 语言是使用最普及的 在C 11版本之前 它们的语法是比较相似的 只不过C 提供了面向对象的编程方式 虽然C 语言是从C语言发展而来的 但是今天的C 已经不是当年的C语言的扩展了 从2011版本开始 更像是一
  • c语言string函数的用法_C语言奇淫技巧,字符串的三种表示方法,不会用不是合格的程序员...

    1 在C语言中 是将字符串作为字符数组来处理的 字符串是逐个存放到数组元素中的 例如用一个一维的字符数组存放字符串 I am a boy 如下代码 char c 12 I a m a b o y 这个字符串的实际长度是11 数组长度是12
  • 【红队技术】第二节:信息收集

    https note youdao com s M5U3LWvw
  • 如何高效率提出问题?

    前言 我们总是对自己 不太熟悉 的东西 但是又迫切想知道其答案 所以总是 匆匆 的像他人提出问题 然而 我们发现一个现象 为什么大多数时候 我的问题总是很少引起别人的兴趣 言外之意是 我总是不能在 短时间 的得到一个 正确的答案 本篇根据笔
  • Oracle检查点队列–实例崩溃恢复原理剖析

    检查点队列 实例崩溃恢复原理剖析 什么叫检查点队列 检查点队列是将脏块连接起来 按照第一次脏的数据块依次往后串联起来 形成一个队列 检查点的作用是什么 检查点只是一个数据库事件 它存在的根本意义在于减少崩溃恢复时间 Oracle8i以前是没
  • PHPStorm.WebStrom等系列官方开发工具配置本地项目与运程服务器同步

    PHPStorm WebStrom配置本地项目与运程服务器同步 说明 PHPStorm WebStrom等官方的系统开发工具配置本地项目与运程服务器同步的方法都基本一致没有 几乎没有什么不同之处 我们拿WebStorm为例说一下具体的配置过
  • 背光补偿

    背光补偿能提供在非常强的背景光线前面目标的理想的曝光 无论主要的目标移到中间 上下左右或者荧幕的任一位置 背光补偿也称作逆光补偿或逆光补正 它可以有效补偿摄像机在逆光环境下拍摄时画面主体黑暗的缺陷 当摄像机处于逆光环境中拍摄时 画面会出现黑
  • windows,IDEA各种常用快捷键积累

    windows IDEA各种常用快捷键积累 windows快捷键 1 win shfit s 拖动截屏 2 ctrl alt s 系统录屏 IDEA 1 快速形成main方法 psvm 回车 2 快速形成输出语句 sout 回车 3 内容提
  • [转载]推荐:互联网思维必读十本书

    原文地址 推荐 互联网思维必读十本书 作者 梧桐雨 推荐 互联网思维必读十本书 最近在商界最流行的词汇 莫过于 互联网思维 了 互联网思维 就像一部让人垂涎的武林秘籍 得之可化腐朽为神奇 无论是小米 阿芙精油 或是卖煎饼的黄太吉 都宣称自己
  • 神经网络bn公式_BN、LN、IN、GN、SN归一化

    作者 泛音 公众号 知识交点 该小伙子文章写得不错 感兴趣的大家可以关注下 公众号 知识交点 内容包含 BatchNormalization LayerNormalization InstanceNorm GroupNorm Switcha
  • 解决Docker中运行的MySQL8.0中文乱码

    解决Docker中MySQL8 0乱码问题 环境 Ubuntu版本 21 10 64位 Docker版本 20 10 MySQL版本 8 0 27 正文 MySQL命令行无法展示中文 如下图 进入MySQL容器 docker exec it
  • doris同步作业配置参数修改和注意事项

    创建同步作业 创建数据同步作业的的详细语法可以连接到 Doris 后 执行 HELP CREATE SYNC JOB 查看语法帮助 这里主要详细介绍 创建作业时的注意事项 job name job name是数据同步作业在当前数据库内的唯一
  • 5-FreeSwitch-freeswitch开启录音和使用

    文章目录 一 开启 usr local freeswitch conf dialplan 后面的default添加配置 二 在freeswitch重新加载 F6 或者 reloadxml 三 使用录音 3 1单腿录音 方法一 API 方法二
  • Android Studio 运行 遇到 Failed to read key from keystore

    分享一下我老师大神的人工智能教程 零基础 通俗易懂 风趣幽默 还带黄段子 希望你也加入到我们人工智能的队伍中来 https blog csdn net jiangjunshow Error Execution failed for task
  • 成交量加权动量交易系统

    策略说明 基于动量系统 通过交易量加权进行判断 系统要素 用VWM上穿零轴判断多头趋势 入场条件 价格高于VWM上穿零轴时价格通道 且在SetupLen的BAR数目内 做多 出场条件 空头势多单出场 import DataAPI impor
  • 左式堆的合并

    二叉堆对于合并操作是困难的 因为需要把一个数组拷贝到另一个数组 左式堆可以高效的地支持合并操作 左式堆与二叉树之间唯一区别是 左式堆不是平衡的 可能非常趋向不平衡 左式堆的结构 typedef struct TreeNode element