【STL】顺序容器 — heap
来源:互联网 发布:雅各比矩阵 编辑:程序博客网 时间:2024/04/29 01:18
heap不属于STL容器,它扮演者priority queue的助手。heap是一种完全二叉树,可由数组来实现,但heap需要动态改变大小,所以最终选择了vector作为底层容器。STL默认提供最大堆。
题外话:分析heap的源码就能清楚的理解堆这种数据结构的例程,而STL库代码的质量又很高,所以看堆的代码,STL源码是一个很好的选择。
为了满足完全二叉树的性质,新插入的元素一定最后一个叶子节点,也就是容器尾端,再然后再进行上滤操作,让新元素找到正确的位置。以push_heap为例:
template <class RandomAccessIterator> // 新元素已插入容器尾部inline void push_heap(RandomAccessIterator first, RandomAccessIterator last) { __push_heap_aux(first, last, distance_type(first), value_type(first));}
这个函数已经假设新插入元素已经位于vector的尾端,所以last指向新元素之后的一个位置。distance_type和value_type都是通过特性萃取机(iterator_traits)提取迭代器的相应类型:difference_type和value_type。提取过程如下:
template <class Iterator>inline typename iterator_traits<Iterator>::difference_type*distance_type(const Iterator&) { // 决定迭代器difference_type return static_cast<typename iterator_traits<Iterator>::difference_type*>(0);} template <class Iterator>inline typename iterator_traits<Iterator>::value_type*value_type(const Iterator&) { // 决定迭代器value_type return static_cast<typename iterator_traits<Iterator>::value_type*>(0);}
注意,这里使用了static_cast把0进行了转换,由于我们是需要迭代器所内嵌的类型,而不关心具体值,所以用0来代替是OK的。
push_heap内部调用函数__push_heap_aux,代码如下:
template <class RandomAccessIterator, class Distance, class T>inline void __push_heap_aux(RandomAccessIterator first, RandomAccessIterator last, Distance*, T*) { __push_heap(first, Distance((last - first) - 1), Distance(0), T(*(last - 1))); // 新插入元素值}
最后两个参数只有类型名,没有参数名,印证了前面的说法。这个函数内部又调用了一个__push_heap函数,这个函数做了实际的上滤操作。在看__push_heap的源码之前,先分析一下它的四个参数:
- first:迭代器,指向容器开头。
- Distance((last - first) - 1):last - first - 1是新插入元素的下标值,这里用了一个C风格的类型转换,符合泛型思想。
- Distance(0):根元素的下标值,同样进行了类型转换。
- T(*(last - 1)):新插入元素的元素值,是上滤操比较操作的基础。
下面是核心代码:
template <class RandomAccessIterator, class Distance, class T>void __push_heap(RandomAccessIterator first, Distance holeIndex, Distance topIndex, T value) { Distance parent = (holeIndex - 1) / 2; // 父节点下标 while (holeIndex > topIndex && *(first + parent) < value) { // value为新插入元素值 *(first + holeIndex) = *(first + parent); holeIndex = parent; // 上移 parent = (holeIndex - 1) / 2; // 上移 } *(first + holeIndex) = value;}
SGI STL的heap,元素是从vector的下标0开始排的,知道了这一点,看这段代码就很轻松了。
参考:
《STL源码剖析》 P172.
0 0
- 【STL】顺序容器 — heap
- STL容器 — 顺序容器
- STL容器(五)——heap
- 【STL】顺序容器 — stack
- 【STL】顺序容器 — queue
- 【STL】顺序容器 — priority_queue
- 【STL】顺序容器 — slist
- STL序列式容器 - heap
- STL学习——顺序容器
- STL——顺序容器的总结
- STL——顺序容器使用总结
- STL源码剖析—顺序容器
- STL容器之顺序容器
- STL 顺序容器,关联容器
- 【STL】容器 > 顺序容器 > vector
- STL之顺序容器
- STL顺序容器
- STL基本顺序容器
- 1.(c# JAVA 基于DataTable通信)
- 为QLabel增加Clicked信号
- CloudFoundry Quota Plans 配额计划
- dd
- 宏的使用
- 【STL】顺序容器 — heap
- 无法获得锁 /var/lib/dpkg/lock - open (11: 资源暂时不可用)
- [ACM] hdu 1003 Max Sum(最大子段和模型)
- rails中获取url信息的一些方法
- Add comments to a regular expression (为正则表达式加注释)
- 大端模式和小端模式
- C语言基础—语言概述、关键字、标识符和注释
- 用SecureCRT来上传和下载文件
- 基于Java的ArcEngine功能服务封装-以soap服务为例