前面是一些小Tips和关键点,以及代码里不好理解的点,后面是源码,重要的函数全部都写了满满的注释嘿嘿嘿!
为什么是这种形式呢,因为看书的时候就是讲解源码的,于是顺着读代码的时候就加了注释。
heap
-
heap不归属于STL容器组件,是扮演priority queue(允许任何次序推入容器内,但取出一定是从优先权最高的元素开始取)的助手。binary max heap就适合做它的底层机制。关键:内部排序!
-
binary heap:完全二叉树的形态(好处:可用array存储所有节点,左右子节点为2i和2i+1,父节点i/2,称为隐式表述法)。故heap是一个array和一组heap算法,为了动态改变大小,用vector代替array。
-
heap分为max-heap和min-heap,STL默认前者。不提供遍历,故没有迭代器。
-
push_heap:上溯程序
-
pop_heap:去掉根节点,下溯。注意:pop取走根节点的操作实际上是将其移至底部容器vector的最后一个元素,为了维持二叉树,需要将下一层的最右节点拿掉,补充到上面的空缺。
-
调用方法:(以算法形式呈现)vector< int> a; make_heap(a.begin(),a.end());
a.push_back(7); push_heap(a.begin(),a.end());
pop_heap(a.begin(),a.end());
sort_heap(a.begin(),a.end());
#ifndef __SGI_STL_INTERNAL_HEAP_H
#define __SGI_STL_INTERNAL_HEAP_H
__STL_BEGIN_NAMESPACE
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma set woff 1209
#endif
//这组push_back()不允许指定“大小比较标准”
//first是头结点存放的下标(并不默认就是0)
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) {
// 当尚未到达顶端且父节点小于新值,fisrt是起始点
*(first + holeIndex) = *(first + parent);//令洞值为父值
holeIndex = parent;//调整洞号,向上提升至父节点
parent = (holeIndex - 1) / 2;//新洞的父节点
} //持续至顶端或满足heap次序特性为止
*(first + holeIndex) = value;//令洞值为新值,完成插入操作
}
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)));
//容器的最尾端为第一个洞号
}
template <class RandomAccessIterator>
inline void push_heap(RandomAccessIterator first, RandomAccessIterator last) {
//注意此函数被调用时新元素应该已经置于底部容器的最尾端
__push_heap_aux(first, last, distance_type(first), value_type(first))