STL之heap的make_heap函数
来源:互联网 发布:绅士之庭邀请码 淘宝 编辑:程序博客网 时间:2024/06/07 07:46
在看侯捷翻译的STL源码剖析时,发现关于heap这一节点错误,特此指出.
1 make_heap源码
template <class _RandomAccessIterator>inline void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last){ __make_heap(__first, __last, __VALUE_TYPE(__first), __DISTANCE_TYPE(__first));}
make_heap用的是__make_heap函数.
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--; }}
这是建heap的标准过此,即从(n-1)/2 到 0, 调用__adjust_heap进行最大堆性质的保持.注: n为最后一个元素的下标(0 , 1, ... n).
3 __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);}
这个函数比较关键,与我们常写的的方法不太一样.假设当前节点为p, 通常的方法是:
- 找到p的左右孩子(如果有)中最大值m
- 若p的值大于m,没有破坏最大堆性质,直接退出.
- 若p的值小于m, 则交互p与最大的孩子的值,同时p指向交换的孩子,继续第一步.
而上面的__adjust_heap并没有父节点与最大孩子节点值的比较,而是直接给父节点赋值最大孩子的值,并下溯.
唯一的不同在于__adjust_heap调用了__push_heap函数.
然而侯捷指出:
可以将__push_heap改为*(first+holeIndex) = value;一下子然我蒙啦,想了许久都没想通.
4 __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;}
__push_heap相当于在堆中插入一个元素.即对空洞位置的调整.不过,为什么追求高效的STL要这么写呢?
如果对一个已是最大堆的堆再调用make_heap,举例:
最大堆: [3, 2, 1]
按STL的实现将会这样执行
1) 将父节点值3保存到变量value中,这样父节点将变成空洞节点记为p. [ p, 2, 1]
2) 找孩子节点的最大值,赋值给空洞节点p = 2,空洞节点p下溯到左孩子. [2, p, 1]
3) 再次计算左右孩子位子,超出范围,调用__push_heap函数,
4) 调整p的位置,又将2回归到原来位置, 退出while循环.[p, 2, 1]
5) 将value赋值到空洞节点. [3, 2, 1],完成.
本人觉得,还不如直接按照常规方法,在adjust_heap比较父节点和最大孩子节点的值.这样效率更高.
至于STL为什么这么写,如果有读者知道,请给我留言.
1 0
- STL之heap的make_heap函数
- STL中heap相关函数的用法:make_heap,push_heap,pop_heap...
- STL---heap概述,make_heap,sort_heap,pop_heap,push_heap。
- STL---heap概述,make_heap,sort_heap,pop_heap,push_heap
- STL---heap概述,make_heap,sort_heap,pop_heap,push_heap
- STL---heap概述,make_heap,sort_heap,pop_heap,push_heap。
- STL---heap概述,make_heap,sort_heap,pop_heap,push_heap
- 【STL】Heap算法——push_heap、pop_heap、sort_heap、make_heap
- STL中关于heap的函数
- STL源码解析 - make_heap
- STL make_heap使用
- STL 中make_heap学习
- stl之heap、stack的用法
- STL之heap堆的应用
- priority_queue 调用 STL里面的 make_heap(), pop_heap(), push_heap() 算法
- STL 之 heap
- STL之heap
- STL之heap 堆
- JavaScript权威指南_123_第15章_脚本化文档_15.4-属性-数据集属性
- leetcode Median of Two Sorted Arrays
- 教你来彻底理解ldpi、mdpi、hdpi、xhdpi、xxhdpi
- 日经春秋 20150704
- Python学习笔记(2)
- STL之heap的make_heap函数
- linux网络设备驱动DM9000驱动分析(1)
- IOS开发>>基于mac系统的apache服务器的使用流程
- 日经社説 20150704 拉致調査で北朝鮮に圧力を
- UIImagePickerController本地化控件文字
- 如何开始一个模块化可扩展的Web App
- ns3 计数器使用方法
- 日经社説 20150704 多様な試みを支援してこそ地方創生だ
- android编辑 webView加载有道网页