STL中vector建立最大堆和最小堆

1.堆的概念:

堆是一种非线性结构,可以把堆看作一个数组,也可以被看作一个完全二叉树,通俗来讲堆其实就是利用完全二叉树的结构来维护的一维数组按照堆的特点可以把堆分为大顶堆和小顶堆

  • 大顶堆:每个结点的值都大于或等于其左右孩子结点的值
  • 小顶堆:每个结点的值都小于或等于其左右孩子结点的值
    (堆的这种特性非常的有用,堆常常被当做优先队列使用,因为可以快速的访问到“最重要”的元素)

2.heap性质

heap本质是用一个数组表示的完全二叉树,并且父节点总是大于(或者小于)子节点的值。在STL中用于实现优先队列(priority_queque)。堆排序是排序算法中是稳定效率最高的一种。STL以可以动态扩容的vector作为heap的底层数组。

一、建堆

vector<int> nums = {9, 6, 2, 4, 7, 0, 1, 8, 3, 5};
  1. 如果使用nums构建最大堆:(堆首为最大值)
make_heap(nums.begin(), nums.end());//默认建的为最大堆
//或
make_heap(nums.begin(), nums.end(), less<int>());
  • 输出nums的结果为
9 8 2 6 7 0 1 4 3 5 

2、如果使用nums构建最小堆:

make_heap(nums.begin(), nums.end(), greater<int>());
  • 输出nums的结果为
0 3 1 4 5 2 9 8 6 7 

将front(即第一个最大元素)移动到end的前部,同时将剩下的元素重新构造成(堆排序)一个新的heap。
时间复杂度是: (2*log(last - first))

二、调整堆

当使用上述的make_heap()建完堆后,如果vector使用push_back()插入数据或pop_back()删除数据后,会破坏最大堆/最小堆的性质,所以需要调整堆,常用push_heap()和pop_heap()两个方法

更新堆

push_heap()用法是,vector先push_back(),后push_heap():

nums.push_back(10);
push_heap(nums.begin(), nums.end(), less<int>());
  • 输出nums的结果:
//原vector 
9 8 2 6 7 0 1 4 3 5 
//push_back()后
9 8 2 6 7 0 1 4 3 5 10
//push_heap()后
10 9 2 6 8 0 1 4 3 5 7 
  • push_heap分析
    为满足完全二叉树的条件,新加入元素一定要放在最下一层作为叶子节点,并填补由左至右的第一个空格,也就是把新元素插入到底层vector的end()处。下图是push_heap算法的实际示意图:
    在这里插入图片描述
    从图中可以看出push_heap算法的过程是将新加入堆的值(50),层层上挪,直到正确的位置。

删除堆首元素

pop_heap()用法是,先pop_heap(),vector后pop_back():

pop_heap(nums.begin(), nums.end(), less<int>());
nums.pop_back();

输出nums的结果:

//原vector
9 8 2 6 7 0 1 4 3 5 
//pop_heap()后
8 7 2 6 5 0 1 4 3 9 
//pop_back()后
8 7 2 6 5 0 1 4 3 

原理:堆其实就是把vector内的元素最大值或最小值转移到nums[0]上。而pop_heap()是将nums[0]放到堆尾部,继而调用vector清除队尾

  • pop_heap分析
    pop_heap操作取走根节点,其实是移至底部容器vector的最后一个节点处并保存该节点。而此时需要维护vector.size()-1大小堆,需要为保存的节点在堆中找一个适当的位置。这个过程和上面的__push_heap的过程恰好相反,从根节点(此时为洞节点),层层下放,直到叶子节点位置,然后在这个位置调用push_heap加入刚刚保存的新值。下面是pop_heap算法实际示意图:在这里插入图片描述

为什么pop_heap()的用法要反过来呢?

要从我们的目的来考虑,使用pop_heap()的绝大部分目的是要把堆顶元素pop出堆中,因为它最大或最小。如果先用vector的pop_back(),它删除的不是堆顶元素(nums[0]),而是vector的最后一个元素。可见这不是我们想要的结果:对于最大堆,最后一个元素既不是最大,也不一定是最小;对于最小堆,最后一个元素既不是最小,也不一定是最大。pop出来没有意义。

观察pop_heap()对堆做了什么?

pop_heap()把堆顶元素放到了最后一位,然后对它前面的数字重建了堆。这样一来只要再使用pop_back()把最后一位元素删除,就得到了新的堆。

堆简介

堆并不是STL的组件,但是经常充当着底层实现结构。比如优先级队列(Priority Queue)等等。

  • 堆是一种完全二叉树,因此我们可以用数组来存储所有节点。在这里的实现中,采用了一个技巧:将数组中索引为0的元素保留,设置为极大值或者为极小值(依据大顶堆或者小顶堆而定)。那么当某个节点的索引是i时,其左子节点索引为2i,右子节点索引为2i+1.父节点是i/2(这里/表示高斯符号,取整)。这种以数组表示树的方式,我们成为隐式表述法(implicit reprentation)。我们这里用C++ STL中的容器vector实现替代数组的功能。

在这里插入图片描述

堆的主要相关算法介绍

  • push_heap算法
    此操作是向堆中添加一个节点。为了满足完全二叉树的条件,新加入的元素一定放在最下面的一层作为叶节点,并填补在由左至右的第一个空格,在这里放在底层容器vector的end()处。
    很显然,新元素的加入很可能使得堆不在满足大顶堆的性质—每个节点的键值都大于或等于其子节点的键值。为了调整使得其重新满足大顶堆的特点,在这里执行一个上溯(percolate up)操作:将新节点与父节点比较,如果其键值比父节点大,就交换父子的位置,如此一直上溯,直到不需要交换或者到根节点为止。
  • pop_heap算法
    此操作取走根节点,放在底端。然后对比第二层的B、C大(假设对比规则是“a>b”)的枝干放在前面,小的放在后面。

例如:
如果: B > C
则结果是: BDEHIJ + CFG + A
PS:只对比一次

  • make_heap算法
    此操作是依据已有的各元素构建堆。
    其中,各元素已经存放在底层容器vector中。
    构建堆实质是一个不断调整堆(即前面pop_heap算法中的调整堆的操作)的过程—通过不断调整子树,使得子树满足堆的特性来使得整个树满足堆的性质。
    叶节点显然需要调整,第一个需要执行调整操作的子树的根节点是从后往前的第一个非叶结点。从此节点往前到根节点对每个子树执行调整操作,即可构建堆。

  • sort_heap算法
    堆排序算法。执行此操作之后,容器vector中的元素按照从小到大的顺序排列。
    构建大顶堆之后,不断执行pop_heap算法取出堆顶的元素,即可。因为每次取得的是最大的元素,将其放在容器vector的最尾端。所以到最后vector中的元素是从小到大排列的。
    PS: sort_heap时,必须先是一个堆(两个特性:1、最大元素在第一个 2、添加或者删除元素以对数时间),因此必须先做一次make_heap.

参考1
参考2

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

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

相关文章

结合 AOP 轻松处理事件发布处理日志

结合 AOP 轻松处理事件发布处理日志Intro前段时间&#xff0c;实现了 EventBus 以及 EventQueue 基于 Event 的事件处理&#xff0c;但是没有做日志&#xff08;EventLog&#xff09;相关的部分&#xff0c;原本想增加两个接口&#xff0c; 处理事件发布日志和事件处理日志&…

基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(三)

系列文章使用 abp cli 搭建项目给项目瘦身&#xff0c;让它跑起来完善与美化&#xff0c;Swagger登场数据访问和代码优先自定义仓储之增删改查统一规范API&#xff0c;包装返回模型再说Swagger&#xff0c;分组、描述、小绿锁接入GitHub&#xff0c;用JWT保护你的API异常处理和…

完全卸载软件及电脑软件残留

当我在控制面板的卸载软件里没有发现我要删软件的软件时&#xff0c;只找到了软件的部分安装目录删除&#xff0c;就会发生残留问题&#xff0c;导致软件依旧可以运行。 经过这么多次后&#xff0c;我就找到了我自认为的最优解。首先运行这个软件&#xff1b;之后打开windows任…

真的是计划赶不上变化吗?

「做事容易半途而废&#xff0c;缺乏毅力」&#xff0c;我想100个人里面有99个是这样。更加好玩的是&#xff0c;这99个人里面可能还有不少会劝说别人要坚持……所以&#xff0c;其实我们每个人心里都清楚&#xff0c;一件事情不会“自动完成”&#xff0c;只有靠自己坚持做下去…

关于解决Path被大改,无法直接编辑恢复的问题

为了给eclipse改版&#xff0c;不用更改API&#xff0c;我动了环境变量&#xff0c;因为我的环境变量名称是path&#xff0c;所以当给tomcatTomCAT安装以及使用详细解释配置环境时&#xff0c;我直接新建的Path&#xff0c;把原来的path覆盖掉了&#xff0c;而且在注册表里无法…

Sql Server之旅——第十二站 对锁的初步认识

作为一个开发人员&#xff0c;锁机制也是我们程序员必须掌握的东西&#xff0c;很久之前在学习锁的时候&#xff0c;都是教科书上怎么说&#xff0c;然后我怎么背&#xff0c;缺少一个工具让我们眼见为实。。。如果这样的话&#xff0c;学习一个东西就很容易忘记。。。因为这些…

算法基础

目录枚举例题应用&#xff1a;模拟技巧递归$分治递归分治算法贪心常见题型与动态规划的区别例题&#xff1a;应用排序选择排序冒泡排序插入排序计数排序基数排序二分最大值最小化STL 的二分查找三分法最大化平均值&#xff08;01分数规划&#xff09;枚举 枚举&#xff08;英语…

ABP框架 v2.9发布!

ABP框架和ABP商业版2.9已经发布,这是3.0之前的最后一个版本! 这篇文章将涵盖本次发布中的新增内容.ABP框架2.9有哪些新增内容&#xff1f;你可以中GitHub的发行说明中看到所有的变更.这篇文章将只包括重要特征/变更.预编译Razor Pages在之前的版本, 预构建的页面(应用模块)和视…

最终选型 Blazor.Server:又快又稳!

书接上文&#xff0c;昨天我们快速的走了一遍wasm的开发流程&#xff08;我的『MVP.Blazor』快速创建与部署&#xff09;&#xff0c;总体来说还是很不错的&#xff0c;无论是从技术上&#xff0c;还是从开发上&#xff0c;重点是用C#来开启前端时代&#xff0c;可以开发SPA单页…

博客系统知多少:揭秘那些不为人知的学问(三)

点击上方关注“汪宇杰博客”上篇《博客系统知多少&#xff1a;揭秘那些不为人知的学问&#xff08;二&#xff09;》介绍了博客的基本功能设计要点&#xff0c;本篇介绍博客的协议或标准。1.“博客”的前世今生2.我的博客故事3.谁是博客的受众&#xff1f;4. 博客基本功能设计要…

Sql Server之旅——第十三站 深入的探讨锁机制

上一篇我只是做了一个堆表让大家初步的认识到锁的痉挛状态&#xff0c;但是在现实世界上并没有这么简单的事情&#xff0c;起码我的表不会没有索引对吧&#xff0c;还有就是我的表一定会有很多的连接过来&#xff0c;10:1的读写&#xff0c;很多码农可能都会遇到类似神乎其神的…

后端程序员转行前端,强烈推荐这6个前端UI框架,第二款小程序UI框架颜值最高!...

昨天有个同事问我有没有可以直接上手的前端UI框架。那今天就给大家推荐6个简单、视觉体验好的前端框架没吃过猪肉&#xff0c;肯定见过猪跑&#xff01;Jquery Mobiledemo地址&#xff1a;https://demos.jquerymobile.com/1.1.0/教程地址:https://www.codesocang.com/jquerymob…

Kubernetes引发“军备赛”,K8s真是企业生存的关键吗

导语与许多其他国家一样&#xff0c;英国对云基础架构的需求空前增长。随着学校&#xff0c;办公室&#xff0c;商店和饭店的关闭以应对疫情&#xff0c;云驱动的应用程序应运而生&#xff0c;解决挑战并提供安慰。随着各个年龄段人群的屏幕时间激增&#xff0c;数据中心正努力…

【新插件发布】AzureAD运维Excel版插件,增删改查快10倍c以上!

在笔者的BI项目开发中&#xff0c;用到了Azure的AzureSQL和AzureAS分析服务&#xff0c;此两大服务&#xff0c;可和AzureAD帐号体系打通。而AzureAD帐号&#xff0c;在其免费功能基础功能上&#xff0c;是免费使用的&#xff0c;随着项目开发上线进入运维阶段&#xff0c;Azur…

数论相关

目录符号整除/同余理论常见符号数论函数常见符号其他常见符号位运算与、或、异或取反左移和右移复合赋值位运算符关于优先级位运算的应用有关 2 的幂的应用取绝对值取两个数的最大/最小值操作一个数的二进制位模拟集合操作快速幂模意义下大整数乘法快速乘高精度快速幂欧拉降幂求…

博客系统知多少:揭秘那些不为人知的学问(二)

点击上方关注“汪宇杰博客”上篇《博客系统知多少&#xff1a;揭秘那些不为人知的学问&#xff08;一&#xff09;》介绍了博客的历史、我的博客故事及博客的受众来源。本篇精彩继续&#xff0c;介绍博客基本功能设计要点。1.“博客”的前世今生2.我的博客故事3.谁是博客的受众…

二分+01分数规划+最大化平均值 Dropping tests POJ - 2976

题意&#xff1a; 给你若n个分数&#xff0c;分子a[i]a[i]a[i],分母b[i]b[i]b[i],使满足公式100⋅∑i1nai∑i1nbi100\cdot\tfrac{\sum_{i1}^{n} a_{i}}{\sum_{i1}^{n} b_{i}}100⋅∑i1n​bi​∑i1n​ai​​&#xff0c;求任意去掉k个分数后&#xff0c;公式结果最大值。 题目…

基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(四)

系列文章使用 abp cli 搭建项目给项目瘦身&#xff0c;让它跑起来完善与美化&#xff0c;Swagger登场数据访问和代码优先自定义仓储之增删改查统一规范API&#xff0c;包装返回模型再说Swagger&#xff0c;分组、描述、小绿锁接入GitHub&#xff0c;用JWT保护你的API异常处理和…

莫比乌斯反演/容斥 +2020ICPC 江西省大学生程序设计竞赛 A Simple Math Problem

题目描述 输入描述: 输出描述: 示例1 输入 3 输出 5 分析&#xff1a; 1.这个题其实考的是一个莫比乌斯反演题&#xff0c;但是由于我知识储备不够&#xff0c;没有看出来&#xff0c;题目给的范围可以瞎搞一下&#xff0c;所以下面容斥可以过。 2.转换一下就是一道经典的…

猎鹰与龙飞船基于Linux,采用C++、Chromium与JS开发

最近两天科技界最重大的事件莫过于马斯克的 SpaceX 成功实现了猎鹰 9 号&#xff08;Falcon 9&#xff09;带着龙飞船&#xff08;Crew Dragon&#xff09;成功发射&#xff0c;并使飞船与国际空间站对接&#xff0c;将 NASA 两名宇航员送上了轨道前哨。背后关于 Falcon 9 与 C…