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结构及算法的更多相关文章

  1. STL——heap结构及算法

    heap(隐式表述,implicit representation) 1. heap概述 : vector + heap算法 heap并不归属于STL容器组件,它是个幕后英雄,扮演priority q ...

  2. STL六大组件之——算法小小小小的解析

    参考自侯捷的<stl源码剖析> stl算法主要分为非可变序列算法(指不直接修改其所操作的容器内容的算法),可变序列算法(指可以修改它们所操作的容器内容的算法),排序算法(包括对序列进行排序 ...

  3. STL源码剖析(算法)

    STL中算法是基于迭代器来实现的. 有了容器中迭代器的实现(对operator*.operator++等的重载),STL中大部分算法实现就显得很简单了. 先看一例关于find算法的实现: templa ...

  4. java结构与算法之选择排序

    一 .java结构与算法之选择排序(冒择路兮快归堆) 什么事选择排序:从一组无序数据中选择出中小的的值,将该值与无序区的最左边的的值进行交换. 简单的解释:假设有这样一组数据 12,4,23,5,找到 ...

  5. STL中的所有算法(70个)

    STL中的所有算法(70个)----9种类型(略有修改by crazyhacking) 参考自: http://www.cppblog.com/mzty/archive/2007/03/14/1981 ...

  6. Data01-数据结构和算法绪论

    Data01-数据结构和算法绪论 一.数据结构和算法绪论 1.1 什么是数据结构? 数据结构是一门研究非数值计算的程序设计问题中的操作对象,以及它们之间的关系和操作等相关问题的学科. 程序设计=数据结 ...

  7. C++ STL 常用算术和生成算法

    C++ STL 常用算术和生成算法 accumulate() accumulate: 对指定范围内的元素求和,然后结果再加上一个由val指定的初始值. #include<numeric> ...

  8. STL中的排序算法

    本文转自:STL中的排序算法 1. 所有STL sort算法函数的名字列表: 函数名    功能描述 sort   对给定区间所有元素进行排序 stable_sort 对给定区间所有元素进行稳定排序 ...

  9. 【算法学习】老算法,新姿势,STL——Heap

    “堆”是一个大家很熟悉的数据结构,它可以在\(O(log\;n)\)的时间内维护集合的极值. 这都是老套路了,具体的内部实现我也就不谈了. 我一般来说,都是用queue库中的priority_queu ...

随机推荐

  1. php--常见算法1

    <?php //递归输出123321 function digui($num){ echo $num; if($num<3){ digui($num+1); } echo $num; } ...

  2. 第十章、time模块

    目录 第十章.模块 第十章.模块 time模块 import time 时间戳 表示:是从1970年1月1日00:00:00开始按秒计算的偏移量. time_stamp = time.time() p ...

  3. 经典i++和++i问题(附带运算符优先级问题)

    转自 https://blog.csdn.net/mustard1020/article/details/79617865 1.i++和++i的区别     (1)i++简单来说就是先用i的值来参加表 ...

  4. servlet遇到的问题

    1 创建web项目没有xml自动生成 2  servlet 忽然报奇怪500错误  出现的BUG原因 JAVA bean没有设置  自动导入了其他User包

  5. 基础数据类型(int,str,bool)

    一 python 中的基础数据类型 1.int  数字类型(整数类型)  主要用来数学计算 2.str  字符串   可以保存少量数据进行操作 3.bool  布尔值  判断真假   True  Fa ...

  6. pgsql 相关函数

    1.COALESCE — 空值替换函数.示例:COALESCE(col, 'replacement') :如果col列的值为null,则col的值将被替换为'replacement' 2.regexp ...

  7. 使用幕布时,在Session过期后,弹出框加载出登陆的HTML的问题

    思路:在登陆页面判断当前加载的Url是否时login/index ,如果不是跳转到登陆页 //设置或获取对象指定的文件名或路径. var Url = window.location.pathname; ...

  8. Html中使用Cookie取值赋值

    //设置Cookie function setCookie(name, value) { var Days = 1; var exp = new Date(); exp.setTime(exp.get ...

  9. MySQL Audit日志审计

    一.简介 数据库审计能够实时记录网络上的数据库活动,对数据库操作进行细粒度审计的合规性管理,对数据库受到的风险行为进行告警,对攻击行为进行阻断,它通过对用户访问数据库行为的记录.分析和汇报,用来帮助用 ...

  10. HDFS知识点

    1.通过代码验证集群的配置文件的优先级 HDFS文件上传 1.编写源代码 @Test public void testCopyFromLocalFile() throws IOException, I ...