STL中的堆(heap)操作

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位置上的元素压入堆。
    函数原型:
void push_heap(first,last);
void push_heap(first,last,compare_fuction).
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函数的源代码如下:
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;
}

该函数主要的功能就是将索引为__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);
}

该函数设定__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));
}

可以看到push_heap函数只是简单的调用__push_heap_aux函数.

2. make_heap:利用区间[first,last)中的元素构造一个heap。
  函数原型:
void make_heap(first,last)
void make_heap(first,last ,compare_fuction)
SGI C++ STL的make_heap算法函数是由stl_heap.h文件提供。
它利用了辅助函数__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);
}

该函数其实就是参数__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 <  2return;
  _Distance __len = __last - __first;
  _Distance __parent = (__len -  2)/ 2;
    
   while ( true) {
    __adjust_heap(__first, __parent, __len, _Tp(*(__first + __parent)));
     if (__parent ==  0return;
    __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));
}
直接调用__make_heap来实现的.

3. pop_heap:  假定区间[first,last)中已包含一个堆,将first位置和last-1位置上的值交换,重新把[first,last-1)调整为一个堆。
    函数原型:
void pop_heap(first,last);
void pop_heap(first,last,compare_fuction)
pop_heap主要使用了__pop_heap和__pop_heap_aux两个辅助函数.
(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);
 }  

__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));
}

(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));
}   
  
直接调用__pop_heap_aux完成  
    
4. sort_heap: 对存储在堆中的元素进行排序。
    函数原型:
void sort_heap(first,last);
void sort_heap(first,last,compare_fuction)
时间复杂度是O(nlogn)
实现代码很简单就是不断的调用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--);
}      

转载于:https://www.cnblogs.com/xkfz007/archive/2012/08/25/2655620.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值