0x17 二叉堆

0x17 二叉堆

二叉堆是一种支持插入、删除、查询最值的数据结构。它其实是一种满足“堆性质”的完全二叉树,树上的每一个节点带有一个权值。若树中的任意一个节点的权值都小于等于其父节点的权值,则称该二叉树满足“大根堆性质”,称其为“大根堆”。若树中的任意一个节点的权值都大于等于其父节点的权值,则称该二叉树满足“小根堆性质”,称其为“小根堆”。

根据完全二叉树性质,我们可以采取层次序列储存方式,直接用一个数组保存二叉堆。层次序列存储方式,就是逐层从左往右为树中的节点依次编号,把此编号作为节点在数组中储存的位置(下标)。在这种储存方式中,父节点编号等于子节点编号除以2,左子节点编号等于父节点编号乘2,右子节点编号等于父节点编号乘2加1,如下图所示:

在这里插入图片描述

我们以大根堆为例,探讨堆支持的常见几种操作。

Insert:

insert(val)操作向二叉堆中插入一个带有权值val的新节点。我们吧这个新节点直接放在储存二叉堆的数组末尾,然后通过交换的方式向上调整,直至满足堆性质。其时间复杂度为堆的深度,即 O ( l o g N ) O(logN) O(logN)

在这里插入图片描述

int heap[SIZE],n;
void up(int p) //向上调整
{
    while(p>1)
    {
        if(heap[p]>heap[p/2])
        {
            swap(heap[p],heap[p/2]);
            p/=2;
        }
        else
            break;
    }
}
void insert(int val)
{
    heap[++n]=val;
    up(n);
}

GetTop:

GetTop返回二叉堆的堆顶权值,即最大值heap[1],时间复杂度为 O ( 1 ) O(1) O(1)

Extract:

Extract操作把堆顶元素从二叉堆中移除。我们把堆顶heap[1]与储存数组末尾的节点heap[n]交换,然后移除数组末尾节点(令n减少1),最后把堆顶通过交换的方式向下调整,直至满足堆性质。其时间复杂度为堆的深度,即 O ( l o g N ) O(logN) O(logN)

在这里插入图片描述

void down(int p)
{
    int s=p*2; //p的左子节点
    while(s<=n)
    {
        if(s<n&&heap[s]<heap[s+1])
            s++;
        if(heap[s]>heap[p])
        {
            swap(heap[s],heap[p]);
            p=s,s=p*2;
        }
        else
            break;
    }
}

void Extract()
{
    heap[1]=heap[n--];
    down(1);
}

Remove:

Remove(p)操作把存储在数组下标p位置的节点从二叉堆中删除。与Extract相类似,我们把heap[p]heap[n]交换,然后令n减少1。注意此时heap[p]既有可能需要向下调整,也有可能需要向上调整,需要分别检查和处理。时间复杂度为 O ( l o g N ) O(logN) O(logN)

void remove(int k)
{
    heap[k]=heap[n--];
    up(k),down(k);
}

C++ STL中的priority_queue(优先队列)为实现了一个大根堆,支持push(Insert)top(GetTop)pop(Extract)操作,不支持Remove操作,详细用法参见第0x71节。

1.Huffman

考虑这样一个问题:构造一棵包含 n n n个叶子结点的 k k k叉树,其中第 i i i个叶子结点带有权值 w i w_i wi,要求最小化 ∑ w i ∗ l i \sum w_i*l_i wili,其中 l i l_i li表示第 i i i个叶子结点到根节点的距离。该问题被称为 k k kHuffman树(哈夫曼树)。

为了最小化 ∑ w i ∗ l i \sum w_i*l_i wili,应该让权值大的叶子结点的深度尽可能小。 k = 2 k=2 k=2,我们很容易想到用下面这个贪心算法来求出二叉Huffman树。

1.建立一个小根堆,插入这 n n n个叶子结点的权值。

2.从堆中取出最小的两个权值 w 1 w_1 w1 w 2 w_2 w2,令 a n s + = w 1 + w 2 ans+=w_1+w_2 ans+=w1+w2

3.建立一个权值为 w 1 + w 2 w_1+w_2 w1+w2的树节点 p p p,令 p p p成为权值 w 1 w_1 w1 w 2 w_2 w2的树节点的父亲。

4.在堆中插入权值 w 1 + w 2 w_1+w_2 w1+w2

5.重复第2~4步,直至堆的大小为1。

最后,由所有新建的 p p p与原来的叶子结点构成的树就是Huffman树,变量ans就是 ∑ w i ∗ l i \sum w_i*l_i wili的最小值。

在这里插入图片描述

对于 k ( k > 2 ) k(k>2) k(k>2)Huffman树的求解,直观的想法是在上述贪心算法的基础上,改为每次从堆中取出最小的k个权值。然而仔细思考可以发现,如果在执行最后一轮循环时,堆的大小为 2 ∼ k − 1 2\sim k-1 2k1之间(不足以取出k个),那么整个Huffman树的根的子节点的个数就小于k。这显然不是最优解——我们任取Huffman树中一个深度最大的节点,把它改为根的子节点,就会使 ∑ w i ∗ l i \sum w_i*l_i wili变小。

为此我们可以添加一些权值为0的叶子结点,使叶子结点的个数满足 ( n − 1 )   m o d   ( k − 1 ) = 0 (n-1)\bmod (k-1)=0 (n1)mod(k1)=0,然后“每次从堆中取出最小的k个权值”的贪心想法就是正确的。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序:布局样式

效果 wxml <view class"layout"><view class"left"><view>1</view><view>1</view><view>1</view><view>1</view><view>1</view></view><view class"right"&…

2023 亚马逊云科技 re:Invent 大会探秘:Aurora 无限数据库的突破性应用

文章目录 一、前言二、Amazon Aurora 无限数据库2.1 亚马逊云科技数据库产品发展历程2.2 什么是 Amazon Aurora Limitless Database&#xff08;无限数据库&#xff09;2.3 Amazon Aurora Limitless Database 设计架构2.4 Amazon Aurora Limitless Database 分片功能2.5 使用 A…

c语言:判断是否为整数|练习题

一、题目 输入一个数字&#xff0c;判断该数字是否为整数 如图&#xff1a; 二、思路分析 1、没有小数部分的数字&#xff0c;即为整数。所以&#xff0c;只要知道该数字是否有小数部分&#xff0c;即可。 2、例子&#xff1a;1.5减去10.5&#xff0c;由于有小数部分&#xff0…

跟着官网学 Vue - 插槽

Vue 插槽是一种强大的组件通信方式。 插槽内容与出口 在 Vue 中&#xff0c;插槽是一种让父组件向子组件传递内容的方式。子组件使用 <slot> 元素作为插槽出口&#xff0c;父组件可以通过插槽内容填充这些空白区域。 示例&#xff1a; <!-- MyButton.vue --> &…

解决“bat中文路径乱码“问题

今天&#xff0c;在使用.bat脚本&#xff0c;将hello.png从"D:\mypic\备份"目录&#xff0c;拷贝到"D:\mypic\备份"时&#xff1b;发现中文乱码,弹出如下对话框: 图(1) bat中文路径乱码 原来的命令是&#xff1a; copy D:\mypic\one\hello.png D:\mypic\备…

PIG框架学习1——密码模式登录认证获取Token流程

文章目录 O、前言一、总流程概括&#xff1a;二、具体流程分析PIG提供的具体流程图&#xff1a;鉴权请求报文示例0、网关前置处理1、客户端认证处理2、正式接受登录请求3、组装认证对象4、认证管理器进行认证&#xff08;授权认证调用&#xff09;5、认证成功处理器 O、前言 对…

读取小数部分

1.题目描述 2.题目分析 //假设字符串为 char arr[] "123.4500"; 1. 找到小数点位置和末尾位置 代码如下&#xff1a; char* start strchr(arr, .);//找到小数点位置char* end start strlen(start) - 1;//找到末尾位置 如果有不知道strchr()用法的同学&#xf…

Yapi详细安装过程(亲测可用)

1. 前置条件 1、Git 2、NodeJs&#xff08;7.6&#xff09; 3、Mongodb&#xff08;2.6&#xff09; 2. NodeJs的安装 1、获取资源 curl -sL https://rpm.nodesource.com/setup_8.x | bash - 2、安装NodeJS yum install -y nodejs 3、查看NodeJs和Npm node -v npm -v…

[AI工具推荐]AiRestful智能API代码生成

智能API代码示例生成工具AiRestful 一、产品介绍二、如何使用1、第一步(必须):2、第二步(可选):3、第三步(智能生成): 三、如何集成到您的网站(应用)1、开始接入2、接入案例 四、注意点 一、产品介绍 AiRestful是一款基于智能AI的,帮助小白快速生成任意编程语言的API接口调用示…

centos7安装node-v18版本

背景# 背景就是上一篇文章提到的&#xff0c;部署gitbook这个文档中心的话&#xff0c;是需要先安装node&#xff0c;然后&#xff0c;如果你的node版本过高的话&#xff0c;一般会报错&#xff0c;此时&#xff0c;网上很多文章就是降node版本解决&#xff0c;但其实用高版本…

如何做搜索?如何做搜索优化?如何在搜索领域快速成长?

三年多的搜索研发经历&#xff0c;万亿级集群管理经历&#xff0c;集群优化搜索优化经历。将生产环境的集群&#xff0c;检索性能提升了数十倍。也遇到过大大小小的生产事故。在工作中有幸能够得到前谷歌中国首席架构陈老师的指导。在搜索方面&#xff0c;自己也积累了蛮多的经…

最具挑战的骑行路线

1&#xff0c;318川藏线 2&#xff0c;独库公路 - 561公里 3&#xff0c;珠峰尼泊尔 1000公里 4&#xff0c;沙漠公路 1800公里 5&#xff0c;219新藏线 2500公里 下面是一些别人的骑行记录、证书或奖牌。 参考&#xff1a; 1&#xff0c;抖音 - Max骑行玩家 https://v.douy…

链路聚合 (hcia)

原理 采用链路聚合技术可以在不进行硬件升级的条件下&#xff0c;通过将多个物理接口捆绑为一个逻辑接 口&#xff0c;达到增加链路带宽的目的。在实现增大带宽目的的同时&#xff0c;链路聚合采用备份链路的机制&#xff0c; 可以有效的提高设备之间链路的可靠性 &#x…

Chrome2023新版收藏栏UI改回旧版

版本 120.0.6099.109&#xff08;正式版本&#xff09;Chrome浏览器菜单新版、旧版的差异 想要将书签、功能内容改回旧版的朋友可以网址栏输入&#xff1a;「chrome://flags」&#xff0c;接着搜寻「Chrome Refresh 2023」。 最后将 Chrome Refresh 2023、Chrome Refresh 2023…

如何使用JavaScript 将数据网格绑定到 GraphQL 服务

前言 作为一名前端开发人员&#xff0c;GraphQL对于我们来说是令人难以置信的好用。它可以用来简化数据访问&#xff0c;这让我们的工作变得更加容易。 什么是 GraphQL&#xff1f;它是一个抽象层&#xff0c;位于任意数量的数据源之上&#xff0c;并为您提供一个简单的 API …

学网安:先来学学Python之Excel

在 Python 中&#xff0c;exec 是一个内置函数&#xff0c;允许在运行时动态执行 Python 代码。虽然 exec 的使用需要谨慎&#xff0c;因为它可以导致安全问题和难以调试的代码&#xff0c;但它也提供了一些非常强大的功能。 本文将详细介绍 Python exec 函数的高级用法&#…

GZ015 机器人系统集成应用技术样题5-学生赛

2023年全国职业院校技能大赛 高职组“机器人系统集成应用技术”赛项 竞赛任务书&#xff08;学生赛&#xff09; 样题5 选手须知&#xff1a; 本任务书共 24页&#xff0c;如出现任务书缺页、字迹不清等问题&#xff0c;请及时向裁判示意&#xff0c;并进行任务书的更换。参赛队…

基于linux系统的Tomcat+Mysql+Jdk环境搭建(一)vmare centos7 设置静态ip和连接MobaXterm

特别注意&#xff0c;Windows10以上版本操作系统需要下载安装VMware Workstation Pro16及以上版本&#xff0c;安装方式此处略。 (可忽略 my*** 记录设置的vamare centos7 账号root/aaa 密码&#xff1a;Aa123456 ) 1、命令行和图形界面切换 如果使用的是VMware虚拟机&…

Activiti工作流框架学习笔记(一)之通用数据表详细介绍

文/朱季谦 Activiti工作流引擎自带了一套数据库表&#xff0c;这里面有一个需要注意的地方&#xff1a; 低于5.6.4的MySQL版本不支持时间戳或毫秒级的日期。更糟糕的是&#xff0c;某些版本在尝试创建此类列时将引发异常&#xff0c;而其他版本则不会。执行自动创建/升级时&a…

C/C++ STL提供的关联式容器之unordered_set

unordered_set 容器&#xff0c;直译为[无序set容器]。 unordered_set容器和set容器很像&#xff0c;唯一的区别就在于 set 容器会自行对存储的数据进行排序&#xff0c;而unordered_set容器不会。 unordered_set的几个特性&#xff1a; 1. 不再以键值对的形式存储数据&#x…