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. centos 查看ip

    1.现象: 通过ip addr 查找Ip时,发现ens33中没有inet属性,如下图: 2.解决方法 打开网卡配置文件 /etc/sysconfig/network-scripts/ifcfg-ens ...

  2. XML和XML解析

    1. XML文件: 什么是XML?XML一般是指可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言. 2.XML文件的优点: 1)XML文档内容和结构完全分离. 2 ...

  3. java使用策略模式代替if/else

    平时在开发中避免不了使用大量的if else语句,但过多层的if else对于性能有很大的开销,类似如下代码 public class MainStart { public static void m ...

  4. Dijkstra 优先队列优化

    #include <iostream> #include <queue> #include <vector> using namespace std; ; stru ...

  5. maven-war-plugin

    Name Type Since Description 默认值 cacheFile File 2.1-alpha-1 包含webapp结构的文件缓存 ${project.build.directory ...

  6. error LNK2019 : unresolved external symbol Zbar配置问题

    原文链接:https://blog.csdn.net/MengchiCMC/article/details/77871714 出现error LNK2019 : unresolved external ...

  7. IDEA导入maven中导入net.sf.json报错的解决方法

    使用IDEA搭建Maven项目导入架包时, 添加net.sf.json的jar包的时候,代码如下: 在pom.xml文件时: <dependency> <groupId>net ...

  8. sysbench简易使用

    sysbench简易使用 由于测试需要,需要用到sysbench这个工具.推荐简便使用. # yum 安装 yum install sysbench 创建数据库 CREATE DATABASE `sb ...

  9. Can't specify target table for update in FROM clause

    UPDATE tbl SET col = ( SELECT ... FROM (SELECT.... FROM) AS x); 额外嵌套了一个 SELECT 语句 例如LeetCode 中的 Dele ...

  10. Redis实战(18)Redis位图巧用,节约内存

    序言 资料 https://www.cnblogs.com/luke44/p/12031078.html