《STL源码剖析》---stl_heap.h阅读笔记

Heap堆是常用的数据结构,Heap中也可以存放元素。但是STL中并没有提供Heap容器,只是提供了关于Heap操作的算法。只要支持RandomAccessIterator的容器都可以作为Heap容器。

Heap分为max heap和min heap,max heap中每次取出的结点时heap结构中值最大的结点,min heap中每次取出的结点时heap结构中值最小的结点。

在实际应用中,经常用vector作为heap容器,heap经常作为priority queue。对于二叉堆,这里有描述http://blog.csdn.net/kangroger/article/details/8718732

当向heap中插入元素时,插入到末尾,“向上维护”即可:指的是把插入结点与其父结点比较,如果不符合堆得要求则交换,再向上维护其父结点……

当在heap取出元素时,把末尾元素放到Heap头,"向下维护“即可:指的是父结点与孩子结点比较,如果不满足要求,与较大(较小)一个交换,再维护交换的孩子结点……

Heap不允许遍历其结点,所以Heap没有迭代器。

G++ 2.91.57,cygnus\cygwin-b20\include\g++\stl_heap.h 完整列表
/*
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Hewlett-Packard Company makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 * Copyright (c) 1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Silicon Graphics makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 */

/* NOTE: This is an internal header file, included by other STL headers.
 *   You should not attempt to use it directly.
 */

#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

//向上维护
template <class RandomAccessIterator, class Distance, class T>
void __push_heap(RandomAccessIterator first, Distance holeIndex,
                 Distance topIndex, T value) {
  Distance parent = (holeIndex - 1) / 2;	// 找出父结点
  //父结点不是heap顶 且 父节点的值小于孩子结点(小于号<可以看出STL维护的是max heap)
  while (holeIndex > topIndex && *(first + parent) < value) {
    *(first + holeIndex) = *(first + parent);	// 父结点下调
    holeIndex = parent; // 维护父结点
    parent = (holeIndex - 1) / 2;
  }
  //已达到heap顶或者满足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)));

}

//往heap添加元素。注意:此函数调用时,元素已经添加到末尾了,且迭代器已经加1了
template <class RandomAccessIterator>
inline void push_heap(RandomAccessIterator first, RandomAccessIterator last) {
  // 注意,此函式被呼叫時,新元素應已置於底層容器的最尾端。
  __push_heap_aux(first, last, distance_type(first), value_type(first));
}

//向上维护,允许用自己定义的comp函数,这是未必是max heap了
template <class RandomAccessIterator, class Distance, class T, class Compare>
void __push_heap(RandomAccessIterator first, Distance holeIndex,
                 Distance topIndex, T 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;
}

template <class RandomAccessIterator, class Compare, class Distance, class T>
inline void __push_heap_aux(RandomAccessIterator first,
                            RandomAccessIterator last, Compare comp,
                            Distance*, T*) {
  __push_heap(first, Distance((last - first) - 1), Distance(0),
              T(*(last - 1)), comp);
}

template <class RandomAccessIterator, class Compare>
inline void push_heap(RandomAccessIterator first, RandomAccessIterator last,
                      Compare comp) {
  __push_heap_aux(first, last, comp, distance_type(first), value_type(first));
}

// 以下這個 __adjust_heap() 不允許指定「大小比較標準」
//向下维护heap
template <class RandomAccessIterator, class Distance, class T>
void __adjust_heap(RandomAccessIterator first, Distance holeIndex,
                   Distance len, T value) {
  Distance topIndex = holeIndex;
  Distance secondChild = 2 * holeIndex + 2;	// 找到右孩子的位置
  while (secondChild < len) {//还没到达末尾
    // 比较左右孩子大小, secondChild 代表其中较大者
    if (*(first + secondChild) < *(first + (secondChild - 1)))
      secondChild--;
    // 较大的孩子放到父结点位置
    *(first + holeIndex) = *(first + secondChild);
    holeIndex = secondChild;
    // 维护较大的孩子
    secondChild = 2 * (secondChild + 1);
  }
  // 没有右孩子,只有左孩子,只需维护一次,因为左孩子是heap的最后一个元素
  if (secondChild == len) {
    *(first + holeIndex) = *(first + (secondChild - 1));
    holeIndex = secondChild - 1;
  }

  //把调整值放到合适位置,等价于*(first + holeIndex) = value;
  __push_heap(first, holeIndex, topIndex, value);
}

//向下维护heap
template <class RandomAccessIterator, class T, class Distance>
inline void __pop_heap(RandomAccessIterator first, RandomAccessIterator last,
                       RandomAccessIterator result, T value, Distance*) {
  *result = *first; // 把堆顶的值放到堆尾,堆尾的值保存在参数value中

  __adjust_heap(first, Distance(0), Distance(last - first), value);

}

template <class RandomAccessIterator, class T>
inline void __pop_heap_aux(RandomAccessIterator first,
                           RandomAccessIterator last, T*) {
  __pop_heap(first, last-1, last-1, T(*(last-1)), distance_type(first));
  /*
	根据implicit representation heap的次序性,pop后的结果是容器的第一个元素。
	把最后一个元素放到到容器头,因此维护时维护区间是[first last-1)。
  */
}
//取出heap顶元素,按照max heap属性来维护heap
template <class RandomAccessIterator>
inline void pop_heap(RandomAccessIterator first, RandomAccessIterator last) {
  __pop_heap_aux(first, last, value_type(first));
}

//向下维护heap,允许执行比较函数comp
template <class RandomAccessIterator, class Distance, class T, class Compare>
void __adjust_heap(RandomAccessIterator first, Distance holeIndex,
                   Distance len, T value, Compare comp) {
  Distance topIndex = holeIndex;
  Distance secondChild = 2 * holeIndex + 2;
  while (secondChild < len) {
    if (comp(*(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, comp);
}

// 取出堆顶元素,允许定义比较函数comp
template <class RandomAccessIterator, class T, class Compare, class Distance>
inline void __pop_heap(RandomAccessIterator first, RandomAccessIterator last,
                       RandomAccessIterator result, T value, Compare comp,
                       Distance*) {
  *result = *first;
  __adjust_heap(first, Distance(0), Distance(last - first), value, comp);
}

template <class RandomAccessIterator, class T, class Compare>
inline void __pop_heap_aux(RandomAccessIterator first,
                           RandomAccessIterator last, T*, Compare comp) {
  __pop_heap(first, last - 1, last - 1, T(*(last - 1)), comp,
             distance_type(first));
}
//取出heap顶元素,根据comp调整heap
template <class RandomAccessIterator, class Compare>
inline void pop_heap(RandomAccessIterator first, RandomAccessIterator last,
                     Compare comp) {
    __pop_heap_aux(first, last, value_type(first), comp);
}

template <class RandomAccessIterator, class T, class Distance>
void __make_heap(RandomAccessIterator first, RandomAccessIterator last, T*,
                 Distance*) {
  if (last - first < 2) return;
  Distance len = last - first;

  Distance parent = (len - 2)/2;
    //从heap的中间开始向下维护。一次维护[parent, parent-1,……,0]
  while (true) {

    __adjust_heap(first, parent, len, T(*(first + parent)));
    if (parent == 0) return;
    parent--;
  }
}

// 将 [first,last) 排列成一个 heap。
template <class RandomAccessIterator>
inline void make_heap(RandomAccessIterator first, RandomAccessIterator last) {
  __make_heap(first, last, value_type(first), distance_type(first));
}

template <class RandomAccessIterator, class Compare, class T, class Distance>
void __make_heap(RandomAccessIterator first, RandomAccessIterator last,
                 Compare comp, T*, Distance*) {
  if (last - first < 2) return;
  Distance len = last - first;
  //从heap的中间开始向下维护。一次维护[parent, parent-1,……,0]
  Distance parent = (len - 2)/2;

  while (true) {
    __adjust_heap(first, parent, len, T(*(first + parent)), comp);
    if (parent == 0) return;
    parent--;
  }
}
// 将 [first,last) 排列成一个 heap。允许执行大小比较函数
template <class RandomAccessIterator, class Compare>
inline void make_heap(RandomAccessIterator first, RandomAccessIterator last,
                      Compare comp) {
  __make_heap(first, last, comp, value_type(first), distance_type(first));
}

// 排序(升序)两个迭代器之间的元素,这两个迭代器之间的元素已经满足heap性质了
template <class RandomAccessIterator>
void sort_heap(RandomAccessIterator first, RandomAccessIterator last) {

  /*
	pop_heap()功能是删除heap顶元素,把heap大小减小1,heap顶元素放到末尾。
	由此可以看出,sort的结果是升序。
  */
  while (last - first > 1)
     pop_heap(first, last--); // 每執行 pop_heap() 一次,操作範圍即退縮一格。
}

// 排序(升序)两个迭代器之间的元素,这两个迭代器之间的元素已经满足heap性质了。
//允许指定比较函数comp
template <class RandomAccessIterator, class Compare>
void sort_heap(RandomAccessIterator first, RandomAccessIterator last,
               Compare comp) {
  while (last - first > 1)
     pop_heap(first, last--, comp);
}

#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma reset woff 1209
#endif

__STL_END_NAMESPACE

#endif /* __SGI_STL_INTERNAL_HEAP_H */

// Local Variables:
// mode:C++
// End:

《STL源码剖析》---stl_heap.h阅读笔记

时间: 2024-08-04 13:17:02

《STL源码剖析》---stl_heap.h阅读笔记的相关文章

《STL源码剖析》---stl_hash_set.阅读笔记

STL只规定接口和复杂度,对于具体实现不作要求.set大多以红黑树实现,但STL在标准规格之外提供了一个所谓的hash_set,以hash table实现.hash_set的接口,hash_table都提供了,所以几乎所有的hash_set操作都是直接调用hash_table的函数而已. 除了hash_set,还有hash_multiset,它们两个的关系就像set和multiset的关系,一个不允许键值重复,另外一个允许键值重复.其他实现一样. G++ 2.91.57,cygnus\cygwi

《STL源码剖析》---stl_uninitialized阅读笔记

这节讲解在已分配但未初始化的空间上构造对象(可能是一段内存,构造多个对象). 使内存的配置与对象的构造分离开来.在未初始化的内存上构造对象时,会先判断对象类型是否是POD类型.POD全称是Plain old data,也就是标量类型(基本类型和指针类型)或者传统的C struct类型.POD类型有trivial的constructor.deconstructor.copy.assignment(构造.析构.复制构造函数.赋值操作符)操作,所以对POD类型采用最有效的复制手法,而对non-POD类

STL 源码剖析 stl_numeric.h -- copy

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie copy //唯一对外接口 /*-------------------------------------------------------------------------------------- * copy 函数及其重载形式 */ //完全泛化版本. template<class InputIterator, class OutputIterator> // ? 这里的 In

STL 源码剖析 stl_algobase.h

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.iter_swap 描述:将两个 ForwardIterator 所指的对象对调 源码: //version 1 template <class ForwardIterator1, class ForwardIterator2, class T> inline void __iter_swap(ForwardIterator1 a, ForwardIterator2 b, T*) {

STL 源码剖析 stl_numeric.h

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 描述.源码.示例 version 1:普通操作版本 version 2: 泛化操作版本 1.accumulate 描述:计算 init 和 [first, last) 内所有元素的总和 源码: //version 1 template <class InputIterator, class T> T accumulate(InputIterator first, InputIterato

C++ 《STL源码剖析》学习-vector

本文章是笔者学习<STL源码剖析>的学习笔记,记录的是笔者的个人理解,因为个人的水平有限,难免会有理解不当的地方,而且该书出版的时间比较久,难免会有些不一样.如有不当,欢迎指出. vector是c++中经常用到的数据结构,而且在面试时也会有提及,因此了解vector很重要. 一说到vector,我们就很容易想到另外一个与它十分相似的数据结构,关于它们之间显著的差别,我觉得是在于空间运用的灵活性上.数组是静态的,在声明的时候就要指明其具体的空间大小,而vector是动态的,随着元素的增加,它内部

《STL源码剖析》---stl_pair.h阅读笔记

pair是STL中的模板类型,它可以存储两个元素,它也被称作"对组".在map中已经用到了它,pair其实就是一个struct结构,存有两个public的元素,重载了几个运算符,没有什么成员函数,源代码很简单. G++ 2.91.57,cygnus\cygwin-b20\include\g++\stl_pair.h 完整列表 /* * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy,

《STL源码剖析》---stl_tree.h阅读笔记

STL中,关联式容器的内部结构是一颗平衡二叉树,以便获得良好的搜索效率.红黑树是平衡二叉树的一种,它不像AVL树那样要求绝对平衡,降低了对旋转的要求,但是其性能并没有下降很多,它的搜索.插入.删除都能以O(nlogn)时间完成.平衡可以在一次或者两次旋转解决,是"性价比"很高的平衡二叉树. RB-tree(red black tree)红黑树是平衡二叉树.它满足一下规则 (1)每个节点不是红色就是黑色. (2)根节点是黑色. (3)如果节点为红色,则其子节点比为黑色. (4)任何一个节

《STL源码剖析》---stl_iterator.h阅读笔记

STL设计的中心思想是将容器(container)和算法(algorithm)分开,迭代器是容器(container)和算法(algorithm)之间的桥梁. 迭代器可以如下定义:提供一种方法,能够依序寻访某个容器内的所有元素,而又无需暴露该容器的内部表达方式. 在阅读代码之前,要先了解一个新概念:Traits编程技法 template <class T> struct MyIter { typedef T value_type //内嵌型别声明 T *ptr; MyIter(T *p = 0