STL 源代码分析 算法 stl_heap.h
本文senlie原版的。转载请保留此地址:http://blog.csdn.net/zhengsenlie
heap
-------------------------------------------------------------------------
binary heap 是一种全然二叉树。
隐式表示法:以 array 表述 tree。
小技巧:将 array 的 #0 元素保留。则第 i 个元素的左右子节点各自是 2i 和 2i + 1,
父节点是i/2 --> STL 里没有採用这样的小技巧
将 array 无法动态改变大小,所以用 vector 替代 array
这个文件中提供了各种堆操作的算法,注意没有 heap 类
图 4-20
演示样例:
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std; void display(const vector<int> &v){
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
cout << endl;
}
int main(){
int ia[] = {0,1,2,3,4,8,9,3,5};
vector<int> ivec(ia, ia + sizeof(ia)/sizeof(int));
make_heap(ivec.begin(),ivec.end());
display(ivec); ivec.push_back(7);
push_heap(ivec.begin(), ivec.end());
display(ivec); pop_heap(ivec.begin(), ivec.end());
ivec.pop_back();
display(ivec); sort_heap(ivec.begin(), ivec.end());
display(ivec);
}
源代码:
#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 的次序特性)
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 T>
inline void __push_heap_aux(RandomAccessIterator first,
RandomAccessIterator last, Distance*, T*) {
__push_heap(first, Distance((last - first) - 1), Distance(0),
T(*(last - 1)));
} /*调用此函数时,新元素应已置于底部容器的最尾端
--> 什么时候置的?
--> stl_heap 不正确外开放,仅仅在 STL 内部使用,使用 push_heap 的其它 STL 程序应该注意在调用
push_heap 函数前,将新元素置于 heap 底部容器的最尾端
*/
template <class RandomAccessIterator>
inline void push_heap(RandomAccessIterator first, RandomAccessIterator last) {
__push_heap_aux(first, last, distance_type(first), value_type(first));
} 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;
} //STL 里非常多这样的函数体里直接调用还有一个函数的函数。感觉这样不太好。添加了堆栈的开销,
//为什么不直接就调用里面那个函数呢
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));
} 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) {
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);
} template <class RandomAccessIterator, class T, class Distance>
inline void __pop_heap(RandomAccessIterator first, RandomAccessIterator last,
RandomAccessIterator result, T value, Distance*) {
*result = *first;
__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 操作的结果应该底部容器的第一个元素
__pop_heap(first, last - 1, last - 1, T(*(last - 1)), distance_type(first));
} template <class RandomAccessIterator>
inline void pop_heap(RandomAccessIterator first, RandomAccessIterator last) {
__pop_heap_aux(first, last, value_type(first));
} 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);
} template <class RandomAccessIterator, class T, class Compare, class Distance>
inline void __pop_heap(RandomAccessIterator first, RandomAccessIterator last,
RandomAccessIterator result, T value, Compare comp,
Distance*) {
//将首值(即要 pop 出来的值)存放在 result 所指处。
*result = *first;
//又一次调整 heap 。 洞号为0。欲调整值为 value
__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));
} 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; while (true) {
__adjust_heap(first, parent, len, T(*(first + parent)));
if (parent == 0) return;
parent--;
}
} 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;
//找出第一个须要重排的子树的头部。以 parent 标示出。 Distance parent = (len - 2)/2; while (true) {
__adjust_heap(first, parent, len, T(*(first + parent)), comp);
if (parent == 0) return; //走完根节点。就结束了。
parent--; //实际上就是沿着第一个父节点从左到右调整值使父节点的值大于(或小于)两个子节点
}
} 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));
} template <class RandomAccessIterator>
void sort_heap(RandomAccessIterator first, RandomAccessIterator last) {
//每次运行一次 pop_heap() ,极值被放在尾端
//扣除尾端再运行一次 pop_heap()。次极值又被放在新尾端
//一直这样下去,最后就可以得到排序结果
while (last - first > 1) pop_heap(first, last--);
} 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的更多相关文章
- 《STL源代码分析》---stl_heap.h读书笔记
Heap堆的数据结构是经常使用,Heap它还能够存储元件的.但STL并且不提供Heap集装箱.仅仅提供信息Heap算术运算.只支持RandomAccessIterator该容器可以被用作Heap集装箱 ...
- STL 源代码分析 算法 stl_algo.h -- includes
本文senlie原,转载请保留此地址:http://blog.csdn.net/zhengsenlie includes(应用于有序区间) ------------------------------ ...
- STL 源代码分析 算法 stl_algo.h -- merge
本文senlie原版的,转载请保留此地址:http://blog.csdn.net/zhengsenlie merge (应用于有序区间) ------------------------------ ...
- STL 源代码分析 算法 stl_algo.h -- binary_search
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie binary_search -------------------------------- ...
- STL 源代码分析 算法 stl_algo.h -- pre_permutation
本文senlie原版的,转载请保留此地址:http://blog.csdn.net/zhengsenlie pre_permutation ------------------------------ ...
- 《STL源代码分析》---stl_list.h读书笔记
STL在列表list它是一种经常使用的容器.list不连续双向链表在内存,而且是环形. 理解列表如何操作的详细信息,然后.阅读STL名单上的代码是最好的方法. G++ 2.91.57.cygnus\c ...
- STL 源代码剖析 算法 stl_algo.h -- search
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie search --------------------------------------- ...
- STL源代码分析 集装箱 stl_set.h
本文senlie原版的,转载请保留此地址:http://blog.csdn.net/zhengsenlie set ------------------------------------------ ...
- STL 源代码剖析 算法 stl_algo.h -- partial_sort / partial_sort_copy
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie partial_sort / partial_sort_copy ------------- ...
随机推荐
- [Windows Phone] 如何撰写连接 Wifi、蓝芽、网路、飞航模式的网路设定功能
原文:[Windows Phone] 如何撰写连接 Wifi.蓝芽.网路.飞航模式的网路设定功能 前言 为了可以使自己的 APP 具备操作网路的功能,在本文分享研究心得,包含在 Windows Pho ...
- centos7 设备 mariadb-10
下载地址: http://mirrors.ustc.edu.cn/mariadb/mariadb-10.0.19/source/mariadb-10.0.19.tar.gz 由于用cmake所以线安装 ...
- Blend4精选案例图解教程(一):丰富的形状(Shape)资源
原文:Blend4精选案例图解教程(一):丰富的形状(Shape)资源 Blend4资源面板中内置了丰富的形状素材,为我们在构建程序时提供极大的方便.系统默认内置18种常用形状,通过其属性设置可以自定 ...
- 让Android系统支持ubifs文件系统
原文地址:http://www.cnblogs.com/linucos/p/3279381.html 1. ubifs号称性能比yaffs2 好,同时压缩可读写,文件系统image体较小同时可写,相当 ...
- ASP.NET 运行
ASP.NET 运行 对于ASP.NET开发,排在前五的话题离不开请求生命周期.像什么Cache.身份认证.Role管理.Routing映射,微软到底在请求过程中干了哪些隐秘的事,现在是时候揭晓了.抛 ...
- [LeetCode53]Maximum Subarray
问题: Find the contiguous subarray within an array (containing at least one number) which has the larg ...
- 【YouVersion】 The Bible 圣经App
[YouVersion] The Bible 圣经 App 今天向大家郑重推荐一款非常棒的圣经App : <The Bible> YouVersion 团队开发的全球下载量和安装数目第 ...
- 静态常量(static final)在class文件里是如何的呢?
近期写项目遇到一个问题,来回折腾了几次,最终探究清楚了.不废话.上样例. 背景:由于项目小,没有使用配置文件,全部静态常量都放在Config.java里面了 public class Config { ...
- Swing动画之游戏角色
一.动画效果:实现了飞机飞行的动画效果,也实现了飞机的移动. 二.实现原理: 1.飞机飞行 的效果:事实上也还是重写paintComponent,依照一定的时间间隔更换图片就有了飞行的效果,动画就是更 ...
- 使用 svn+maven+jenkins(hudson)+Publish Over SSH plugins 构建持续集成及自动远程发布体系(转)
1.安装jenkins 2.浏览器访问jenkins主页 http://192.168.0.1:8080/,点击“系统管理” 3.在插件管理中,安装Publish Over SSH插件 4.在系统设置 ...