STL -- heap结构及算法
STL -- heap结构及算法
heap(隐式表述,implicit representation)
1. heap概述 : vector + heap算法
heap并不归属于STL容器组件,它是个幕后英雄,扮演priority queue的助手。顾名思义,priority queue允许用户以任何次序将任何元素推入容器内,但取出时一定是从优先权最高(也就是数值最高)的元素开始取。binary max heap 正是具有这样的特性,适合作为priority queue 的底层机制。
让我们做一点分析。如果使用list 作为priority queue的底层机制,元素出入操作可享常数时间。但是要找到list中的极值,却需要对整个list进行线性扫描。我们也可以改变做法,让元素插入前先经过排序,使得list的元素值总是由小到大(或由大到小),但这么一来,收之东隅却失之桑榆:虽然取得极值以及元素删除操作达到最高效率,可元素的插入却只有线性表现。
比较好的做法是以binary search tree 作为priority queue的底层机制。这么一来,元素的插入和极值的取得就有O(logN) 的表现。但杀鸡用牛刀,未免小题大做,一来binary search tree 的输入需要足够的随机性,二来binary search tree并不容易实现。priority queue 的复杂度,最好介于queue 和 binary search tree 之间,才算适得其所。bianry heap便是这种条件下的适当候选人。
所谓binary heap 就是一种complete binary tree(完全二叉树),也就是说,整棵binary tree 除了最底层的叶节点之外,是填满的,而最底层的叶节点(s)由左至右又不得有空隙。
complete binary tree 整棵树内没有任何节点漏洞,这带来一个极大的好处:我们可以利用array来存储所有节点。假设动用一个小技巧,将array的#0元素保留(或设为无限大或无限小),那么当complete binary tree中的某个节点位于array的i处时,其左子节点必位于array的2i处,其右子节点比位于array的2i+1处,其父节点必位于“i/2”处。通过这么简单的位置规则,array可以轻易实现出complete binary tree。这种以array表述tree的方式,我们称为隐式表述法。
这么一来,我们需要的工具就很简单了:一个array 和 一组 heap算法(用来进行元素操作,并将某一整组数据排列成一个heap)。array的缺点是无法动态改变大小,而heap却需要这项功能,因此,以vector代替array是更好的选择。
根据元素的排列方式,heap可分为max-heap 和 min-heap两种,前者每个节点的键值(key)都大于或等于其子节点键值,后者的每个节点键值都小于或等于其子节点键值。STL提供的是max-heap。
2. heap算法
2.1 push_heap算法:上溯
percolate_up(上溯)程序:将新节点拿来与其父节点比较,如果其键值(key)比父节点大,就父子对换位置。如此一直上溯,直到不需对换或直到根节点为止。
push_heap算法的实现细节参见相关源码。
注意:
(1)为了满足complete binary tree的条件,新加入的元素一定要放在最下一层作为叶节点,便填补在由左至右的第一个空格,也就是把新元素插入在底层vector的end()处。
(2)当push_heap函数被调用时,新元素应已置于底部容器的最尾端。
另: array无法动态改变大小,因此如果heap底层采用array,便不可以对满载的array进行push_heap操作,因为那得先在array尾端增加一个元素。如果对一个满载的array执行push_heap,该函数会将最后一个元素视为新增元素,并将其余元素视为一个完整的heap结构(实际上它们的确是),因此执行后的结果等于原先的heap。
2.2 pop_heap算法:下溯+上溯
下图是 pop_heap算法的实际操演情况。既然身为max-heap,最大值必然在根节点。pop操作取走根节点(其实是设至底部容器vector的尾端节点)后,为了满足complete binary tree的条件,必须割舍最下层最右边的叶节点,并将其值重新安插至max-heap(因此有必要重新调整heap结构)。
为了满足max-heap次序特性(每个节点的键值都大于或等于其子节点键值),我们执行所谓的percolate down(下溯)程序:将空间节点和其较大子节点“对调”,并持续下放,直至叶节点为止。然后将前述被割舍之元素值设给这个“已到达叶层的空间节点”,再对它执行一次percolate up(上溯)程序。
pop_heap算法的实现细节参见相关源码。
注意:
pop_heap之后,最大元素只是被置于底部容器的最尾端,尚未被取走。
2.3 sort_heap算法
既然每次pop_heap可获得heap中键值最大的元素,如果持续对整个heap做pop_heap操作,每次将操作范围从后向前缩减一个元素(因为pop_heap会把键值最大的元素放在底部容器的最尾端),当整个程序执行完毕时,我们便有了一个递增序列。
2.4 make_heap算法
这个算法用来将一段现有的数据转化为一个heap。
make_heap算法实现参见相关源码
3. heap没有迭代器 heap的所有元素都必须遵循特别的(complete binary tree)排列规则,所以heap不提供遍历功能,也不提供迭代器。
STL -- heap结构及算法的更多相关文章
- STL——heap结构及算法
heap(隐式表述,implicit representation) 1. heap概述 : vector + heap算法 heap并不归属于STL容器组件,它是个幕后英雄,扮演priority q ...
- STL六大组件之——算法小小小小的解析
参考自侯捷的<stl源码剖析> stl算法主要分为非可变序列算法(指不直接修改其所操作的容器内容的算法),可变序列算法(指可以修改它们所操作的容器内容的算法),排序算法(包括对序列进行排序 ...
- STL源码剖析(算法)
STL中算法是基于迭代器来实现的. 有了容器中迭代器的实现(对operator*.operator++等的重载),STL中大部分算法实现就显得很简单了. 先看一例关于find算法的实现: templa ...
- java结构与算法之选择排序
一 .java结构与算法之选择排序(冒择路兮快归堆) 什么事选择排序:从一组无序数据中选择出中小的的值,将该值与无序区的最左边的的值进行交换. 简单的解释:假设有这样一组数据 12,4,23,5,找到 ...
- STL中的所有算法(70个)
STL中的所有算法(70个)----9种类型(略有修改by crazyhacking) 参考自: http://www.cppblog.com/mzty/archive/2007/03/14/1981 ...
- Data01-数据结构和算法绪论
Data01-数据结构和算法绪论 一.数据结构和算法绪论 1.1 什么是数据结构? 数据结构是一门研究非数值计算的程序设计问题中的操作对象,以及它们之间的关系和操作等相关问题的学科. 程序设计=数据结 ...
- C++ STL 常用算术和生成算法
C++ STL 常用算术和生成算法 accumulate() accumulate: 对指定范围内的元素求和,然后结果再加上一个由val指定的初始值. #include<numeric> ...
- STL中的排序算法
本文转自:STL中的排序算法 1. 所有STL sort算法函数的名字列表: 函数名 功能描述 sort 对给定区间所有元素进行排序 stable_sort 对给定区间所有元素进行稳定排序 ...
- 【算法学习】老算法,新姿势,STL——Heap
“堆”是一个大家很熟悉的数据结构,它可以在\(O(log\;n)\)的时间内维护集合的极值. 这都是老套路了,具体的内部实现我也就不谈了. 我一般来说,都是用queue库中的priority_queu ...
随机推荐
- centos7 开放/关闭防火墙和端口
--------------------------------------------------------------防火墙----------------------------------- ...
- 怎么处理Win7系统备份还原提示代码0x80042302的错误?
我们都知道Win7系统自带备份还原功能,可以在电脑遇到小问题时通过还原至之前备份的正常系统来解决,非常的方便.但是有些用户在使用备份还原功能时,系统会提示0x80042302错误,这该怎么办呢?下面好 ...
- linux学习笔记七
#文件权限很重要,有些时候删除和新建文件没有权限根本操作不了,linux一切皆是文件,所以必须得了解下权限了. 文件的一般权限 简单的ls -ld 命令就能看到权限,dr-xr-x---补全应该是dr ...
- CTAP: Complementary Temporal Action Proposal Generation论文笔记
主要观点:基于sliding window(SW)类的方法,如TURN,可以达到很高的AR,但定位不准:基于Group的方法,如TAG,AR有明显的上界,但定位准.所以结合两者的特长,加入Comple ...
- kubernetes之NFS动态提供Kubernetes后端存储卷
StorageClass作为对存储资源的抽象定义, 对用户设置的NFS申请屏蔽后端存储的细节, 一方面减少了用户对于存储资源细节的关注, 另一方面减轻了管理员手工管理pv的工作, 由系统自动完成pv的 ...
- js失效问题
由于有些公司设计的js文件涉及到收费问题,提供的这些js文件不能部署到线上,只能通过127.0.0.1:8080/home类似方式访问js才能生效,换作10.140.111.11:8080/home这 ...
- linux基础—课堂随笔05_文本三剑客之SED
1.简介 sed是非交互式的编辑器,它不会修改文件,除非使用shell重定向来保存结果.默认情况下,所有的输出行都被打印到屏幕上. sed编辑器逐行处理文件(或输入),并将结果发送到屏幕.具体过程如下 ...
- 版本控制工具 svn 一
一.svn 概述 1).svn的作用 1.多人协作开发:2.远程控制:3.版本控制 2).软件控制管理工具发展之路 SCM:软件配置管理,所谓的软件配置管理实际就是软件源代码的 控制与管理. CVS: ...
- 两步创建vue全局组件
import Login from './Login' export default { install: function(Vue){ Vue.component('Login', Login); ...
- 记录weblogic12c通用版本在windowsXP上安装报异常的问题:java.lang.NoClassDefFoundError:
先上图: 这个可能有经验的人一眼就看出问题了,报这个错的原因是:我把安装包放在了中文目录下,本来以为安装包放在中文目录下无关紧要,但是weblogic12c就是这么神奇,不能放在中文目录下. 解决方法 ...