STL中并没有把heap作为一种容器组件,heap的实现亦需要更低一层的容器组件(诸如list,array,vector)作为其底层机制。Heap是一个类属算法,包含在algorithm头文件中。
在STL中为堆heap的创建和操作提供了4种算法:make_heap,pop_heap,push_heap和sort_heap。
1. push_heap: 假定区间[first,last-1)已经包含了一个堆,把区间[first,last)调整为一个堆(从而 把last-1位置上的元素压入堆。
函数原型:
push_heap是将[first,last)调整为堆。它假定[first,last-1)是一个堆。如果[first,last-1)不是一个堆,push_heap是不负责将它调整为堆的。其实push_heap的操作就是对插入容器的最后一个元素进行调整:判断它与父节点大小,如果大于父节点就将父节点下移到该位置,然后继续将它与之后的父节点比较,知道比较到根节点。所以,如果原来[first,last-1)不是一个堆的话,push_heap后的结果不保证是一个堆。
SGI STL在实现push_heap的时候采用了其他的一些辅助函数,包括__push_heap和__push_heap_aux。
(1)__push_heap函数的源代码如下:
该函数主要的功能就是将索引为__holeIndex、值为value的元素,依照堆的大小关系,上调到topIndex元素位置下面(甚至会调整到__topIndex元素处)。参数__first给出区间首元素的起始位置,以便其他的元素可用数组方式的索引值访问出来。
(2)__push_heap_aux函数的源代码如下:
该函数设定__topIndex=0(即根节点为上调界限元素),将迭代器区间[__first,__last)的最后一个元素*(__last-1)调整到正确位置,其他的元素依次下调. 其中__last-__first-1就是*(__last-1)元素的索引值.
(3) push_heap的源代码如下:
可以看到push_heap函数只是简单的调用__push_heap_aux函数.
2. make_heap:利用区间[first,last)中的元素构造一个heap。
函数原型:
SGI C++ STL的make_heap算法函数是由stl_heap.h文件提供。
它利用了辅助函数__adjust_heap,__push_heap和__make_heap.
(1) __adjust_heap的源代码如下(省略带有比较函数的):
该函数其实就是参数__first迭代器指示整个二叉树的起始处, __len参数为二叉树的元素个数, __holeIndex和__value表示需要调整的节点的索引和它的值.
(2) 辅助__make_heap函数源代码如下:
该函数利用每层局部调整的__adjust_heap函数再实现__make_heap函数来完成对整个二叉树进行堆调整.
(3) make_heap的源代码:
直接调用__make_heap来实现的.
3. pop_heap: 假定区间[first,last)中已包含一个堆,将first位置和last-1位置上的值交换,重新把[first,last-1)调整为一个堆。
函数原型:
pop_heap主要使用了__pop_heap和__pop_heap_aux两个辅助函数.
(1) __pop_heap的源代码:
__pop_heap辅助函数将堆中的根节点与*result元素交换,再对以*result为根节点的元素的二叉树重新调整为堆.
(2) __pop_heap_aux代码:
(3) pop_heap的源代码:
直接调用__pop_heap_aux完成
4. sort_heap: 对存储在堆中的元素进行排序。
函数原型:
时间复杂度是O(nlogn)
实现代码很简单就是不断的调用pop_heap函数将最大元素移到最后.
在STL中为堆heap的创建和操作提供了4种算法:make_heap,pop_heap,push_heap和sort_heap。
1. push_heap: 假定区间[first,last-1)已经包含了一个堆,把区间[first,last)调整为一个堆(从而 把last-1位置上的元素压入堆。
函数原型:
void push_heap(first,last);
void push_heap(first,last,compare_fuction).
void push_heap(first,last,compare_fuction).
SGI STL在实现push_heap的时候采用了其他的一些辅助函数,包括__push_heap和__push_heap_aux。
(1)__push_heap函数的源代码如下:
template <class _RandomAccessIterator, class _Distance, class _Tp>
void __push_heap(_RandomAccessIterator __first, _Distance __holeIndex, _Distance __topIndex, _Tp __value)
{
_Distance __parent = (__holeIndex - 1) / 2;
while (__holeIndex > __topIndex && *(__first + __parent) < __value) {
*(__first + __holeIndex) = *(__first + __parent);
__holeIndex = __parent;
__parent = (__holeIndex - 1) / 2;
}
*(__first + __holeIndex) = __value;
}
template <class _RandomAccessIterator, class _Distance, class _Tp, class _Compare>
void __push_heap(_RandomAccessIterator __first, _Distance __holeIndex,
_Distance __topIndex, _Tp __value, _Compare __comp)
{
_Distance __parent = (__holeIndex - 1) / 2;
while (__holeIndex > __topIndex && __comp(*(__first + __parent), __value)) {
*(__first + __holeIndex) = *(__first + __parent);
__holeIndex = __parent;
__parent = (__holeIndex - 1) / 2;
}
*(__first + __holeIndex) = __value;
}
void __push_heap(_RandomAccessIterator __first, _Distance __holeIndex, _Distance __topIndex, _Tp __value)
{
_Distance __parent = (__holeIndex - 1) / 2;
while (__holeIndex > __topIndex && *(__first + __parent) < __value) {
*(__first + __holeIndex) = *(__first + __parent);
__holeIndex = __parent;
__parent = (__holeIndex - 1) / 2;
}
*(__first + __holeIndex) = __value;
}
template <class _RandomAccessIterator, class _Distance, class _Tp, class _Compare>
void __push_heap(_RandomAccessIterator __first, _Distance __holeIndex,
_Distance __topIndex, _Tp __value, _Compare __comp)
{
_Distance __parent = (__holeIndex - 1) / 2;
while (__holeIndex > __topIndex && __comp(*(__first + __parent), __value)) {
*(__first + __holeIndex) = *(__first + __parent);
__holeIndex = __parent;
__parent = (__holeIndex - 1) / 2;
}
*(__first + __holeIndex) = __value;
}
该函数主要的功能就是将索引为__holeIndex、值为value的元素,依照堆的大小关系,上调到topIndex元素位置下面(甚至会调整到__topIndex元素处)。参数__first给出区间首元素的起始位置,以便其他的元素可用数组方式的索引值访问出来。
(2)__push_heap_aux函数的源代码如下:
template <class _RandomAccessIterator, class _Distance, class _Tp>
inline void __push_heap_aux(_RandomAccessIterator __first, _RandomAccessIterator __last, _Distance*, _Tp*)
{
__push_heap(__first, _Distance((__last - __first) - 1), _Distance(0), _Tp(*(__last - 1)));
}
template <class _RandomAccessIterator, class _Compare, class _Distance, class _Tp>
inline void __push_heap_aux(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp, _Distance*, _Tp*)
{
__push_heap(__first, _Distance((__last - __first) - 1), _Distance(0), _Tp(*(__last - 1)), __comp);
}
inline void __push_heap_aux(_RandomAccessIterator __first, _RandomAccessIterator __last, _Distance*, _Tp*)
{
__push_heap(__first, _Distance((__last - __first) - 1), _Distance(0), _Tp(*(__last - 1)));
}
template <class _RandomAccessIterator, class _Compare, class _Distance, class _Tp>
inline void __push_heap_aux(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp, _Distance*, _Tp*)
{
__push_heap(__first, _Distance((__last - __first) - 1), _Distance(0), _Tp(*(__last - 1)), __comp);
}
该函数设定__topIndex=0(即根节点为上调界限元素),将迭代器区间[__first,__last)的最后一个元素*(__last-1)调整到正确位置,其他的元素依次下调. 其中__last-__first-1就是*(__last-1)元素的索引值.
(3) push_heap的源代码如下:
template <class _RandomAccessIterator>
inline void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
__STL_REQUIRES(_RandomAccessIterator, _Mutable_RandomAccessIterator);
__STL_REQUIRES(typename iterator_traits<_RandomAccessIterator>::value_type, _LessThanComparable);
__push_heap_aux(__first, __last, __DISTANCE_TYPE(__first), __VALUE_TYPE(__first));
}
template <class _RandomAccessIterator, class _Compare>
inline void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
{
__STL_REQUIRES(_RandomAccessIterator, _Mutable_RandomAccessIterator);
__push_heap_aux(__first, __last, __comp, __DISTANCE_TYPE(__first), __VALUE_TYPE(__first));
}
inline void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
__STL_REQUIRES(_RandomAccessIterator, _Mutable_RandomAccessIterator);
__STL_REQUIRES(typename iterator_traits<_RandomAccessIterator>::value_type, _LessThanComparable);
__push_heap_aux(__first, __last, __DISTANCE_TYPE(__first), __VALUE_TYPE(__first));
}
template <class _RandomAccessIterator, class _Compare>
inline void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
{
__STL_REQUIRES(_RandomAccessIterator, _Mutable_RandomAccessIterator);
__push_heap_aux(__first, __last, __comp, __DISTANCE_TYPE(__first), __VALUE_TYPE(__first));
}
可以看到push_heap函数只是简单的调用__push_heap_aux函数.
2. make_heap:利用区间[first,last)中的元素构造一个heap。
函数原型:
void make_heap(first,last)
void make_heap(first,last ,compare_fuction)
void make_heap(first,last ,compare_fuction)
它利用了辅助函数__adjust_heap,__push_heap和__make_heap.
(1) __adjust_heap的源代码如下(省略带有比较函数的):
template <class _RandomAccessIterator, class _Distance, class _Tp>
void __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex, _Distance __len, _Tp __value)
{
_Distance __topIndex = __holeIndex;
_Distance __secondChild = 2 * __holeIndex + 2;
while (__secondChild < __len) {
if (*(__first + __secondChild) < *(__first + (__secondChild - 1)))
__secondChild--;
*(__first + __holeIndex) = *(__first + __secondChild);
__holeIndex = __secondChild;
__secondChild = 2 * (__secondChild + 1);
}
if (__secondChild == __len) {
*(__first + __holeIndex) = *(__first + (__secondChild - 1));
__holeIndex = __secondChild - 1;
}
__push_heap(__first, __holeIndex, __topIndex, __value);
}
void __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex, _Distance __len, _Tp __value)
{
_Distance __topIndex = __holeIndex;
_Distance __secondChild = 2 * __holeIndex + 2;
while (__secondChild < __len) {
if (*(__first + __secondChild) < *(__first + (__secondChild - 1)))
__secondChild--;
*(__first + __holeIndex) = *(__first + __secondChild);
__holeIndex = __secondChild;
__secondChild = 2 * (__secondChild + 1);
}
if (__secondChild == __len) {
*(__first + __holeIndex) = *(__first + (__secondChild - 1));
__holeIndex = __secondChild - 1;
}
__push_heap(__first, __holeIndex, __topIndex, __value);
}
该函数其实就是参数__first迭代器指示整个二叉树的起始处, __len参数为二叉树的元素个数, __holeIndex和__value表示需要调整的节点的索引和它的值.
(2) 辅助__make_heap函数源代码如下:
template <class _RandomAccessIterator, class _Tp, class _Distance>
void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Tp*, _Distance*)
{
if (__last - __first < 2) return;
_Distance __len = __last - __first;
_Distance __parent = (__len - 2)/2;
while (true) {
__adjust_heap(__first, __parent, __len, _Tp(*(__first + __parent)));
if (__parent == 0) return;
__parent--;
}
}
void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Tp*, _Distance*)
{
if (__last - __first < 2) return;
_Distance __len = __last - __first;
_Distance __parent = (__len - 2)/2;
while (true) {
__adjust_heap(__first, __parent, __len, _Tp(*(__first + __parent)));
if (__parent == 0) return;
__parent--;
}
}
该函数利用每层局部调整的__adjust_heap函数再实现__make_heap函数来完成对整个二叉树进行堆调整.
(3) make_heap的源代码:
template <class _RandomAccessIterator>
inline void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
__STL_REQUIRES(_RandomAccessIterator, _Mutable_RandomAccessIterator);
__STL_REQUIRES(typename iterator_traits<_RandomAccessIterator>::value_type,
_LessThanComparable);
__make_heap(__first, __last, __VALUE_TYPE(__first), __DISTANCE_TYPE(__first));
}
inline void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
__STL_REQUIRES(_RandomAccessIterator, _Mutable_RandomAccessIterator);
__STL_REQUIRES(typename iterator_traits<_RandomAccessIterator>::value_type,
_LessThanComparable);
__make_heap(__first, __last, __VALUE_TYPE(__first), __DISTANCE_TYPE(__first));
}
3. pop_heap: 假定区间[first,last)中已包含一个堆,将first位置和last-1位置上的值交换,重新把[first,last-1)调整为一个堆。
函数原型:
void pop_heap(first,last);
void pop_heap(first,last,compare_fuction)
void pop_heap(first,last,compare_fuction)
(1) __pop_heap的源代码:
template <class _RandomAccessIterator, class _Tp, class _Distance>
inline void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
_RandomAccessIterator __result, _Tp __value, _Distance*)
{
*__result = *__first;
__adjust_heap(__first, _Distance(0), _Distance(__last - __first), __value);
}
inline void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
_RandomAccessIterator __result, _Tp __value, _Distance*)
{
*__result = *__first;
__adjust_heap(__first, _Distance(0), _Distance(__last - __first), __value);
}
__pop_heap辅助函数将堆中的根节点与*result元素交换,再对以*result为根节点的元素的二叉树重新调整为堆.
(2) __pop_heap_aux代码:
template <class _RandomAccessIterator, class _Tp>
inline void
__pop_heap_aux(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Tp*)
{
__pop_heap(__first, __last - 1, __last - 1,
_Tp(*(__last - 1)), __DISTANCE_TYPE(__first));
}
inline void
__pop_heap_aux(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Tp*)
{
__pop_heap(__first, __last - 1, __last - 1,
_Tp(*(__last - 1)), __DISTANCE_TYPE(__first));
}
(3) pop_heap的源代码:
template <class _RandomAccessIterator>
inline void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
__STL_REQUIRES(_RandomAccessIterator, _Mutable_RandomAccessIterator);
__STL_REQUIRES(typename iterator_traits<_RandomAccessIterator>::value_type,
_LessThanComparable);
__pop_heap_aux(__first, __last, __VALUE_TYPE(__first));
}
inline void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
__STL_REQUIRES(_RandomAccessIterator, _Mutable_RandomAccessIterator);
__STL_REQUIRES(typename iterator_traits<_RandomAccessIterator>::value_type,
_LessThanComparable);
__pop_heap_aux(__first, __last, __VALUE_TYPE(__first));
}
直接调用__pop_heap_aux完成
4. sort_heap: 对存储在堆中的元素进行排序。
函数原型:
void sort_heap(first,last);
void sort_heap(first,last,compare_fuction)
void sort_heap(first,last,compare_fuction)
实现代码很简单就是不断的调用pop_heap函数将最大元素移到最后.
template <class _RandomAccessIterator>
void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
__STL_REQUIRES(_RandomAccessIterator, _Mutable_RandomAccessIterator);
__STL_REQUIRES(typename iterator_traits<_RandomAccessIterator>::value_type, _LessThanComparable);
while (__last - __first > 1)
pop_heap(__first, __last--);
}
void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
__STL_REQUIRES(_RandomAccessIterator, _Mutable_RandomAccessIterator);
__STL_REQUIRES(typename iterator_traits<_RandomAccessIterator>::value_type, _LessThanComparable);
while (__last - __first > 1)
pop_heap(__first, __last--);
}