我查看了C ++ 0x标准,发现要求make_heap不应超过3 * N比较。
即。 heapify一个无序集合可以在O(N)
中完成 /* @brief Construct a heap over a range using comparison functor.
这是为什么?
来源没有给我任何线索(g ++ 4.4.3)
while(true)+ __parent == 0不是线索,而是对O(N)行为的猜测
template<typename _RandomAccessIterator, typename _Compare>
void
make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp)
{
const _DistanceType __len = __last - __first;
_DistanceType __parent = (__len - 2) / 2;
while (true)
{
_ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
__comp);
if (__parent == 0)
return;
__parent--;
}
}
__ adjust_heap看起来像一个log N方法:
while ( __secondChild < (__len - 1) / 2)
{
__secondChild = 2 * (__secondChild + 1);
沼泽标准记录N给我。
template<typename _RandomAccessIterator, typename _Distance,
typename _Tp, typename _Compare>
void
__adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
_Distance __len, _Tp __value, _Compare __comp)
{
const _Distance __topIndex = __holeIndex;
_Distance __secondChild = __holeIndex;
while (__secondChild < (__len - 1) / 2)
{
__secondChild = 2 * (__secondChild + 1);
if (__comp(*(__first + __secondChild),
*(__first + (__secondChild - 1))))
__secondChild--;
*(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
__holeIndex = __secondChild;
}
if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
{
__secondChild = 2 * (__secondChild + 1);
*(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
+ (__secondChild - 1)));
__holeIndex = __secondChild - 1;
}
std::__push_heap(__first, __holeIndex, __topIndex,
_GLIBCXX_MOVE(__value), __comp);
}
为什么这是O <= 3N的任何线索将不胜感激 编辑:
实验结果:
此实际实施使用
答案 0 :(得分:52)
答案 1 :(得分:17)
@templatetypedef已经为build_heap
提供了build_heap
的渐近运行时间 O(n)的原因。 a good answer第2版第6章也有证据。
至于为什么C ++标准要求最多使用 3n 比较:
从我的实验(见下面的代码)看来,实际上需要的是 2n 比较。实际上,CLRS包含def parent(i):
return i/2
def left(i):
return 2*i
def right(i):
return 2*i+1
def heapify_cost(n, i):
most = 0
if left(i) <= n:
most = 1 + heapify_cost(n, left(i))
if right(i) <= n:
most = 1 + max(most, heapify_cost(n, right(i)))
return most
def build_heap_cost(n):
return sum(heapify_cost(n, i) for i in xrange(n/2, 1, -1))
仅使用 2(n-⌈logn⌉)比较的证明。
标准的界限似乎比要求的更加慷慨。
n 10 20 50 100 1000 10000
build_heap_cost(n) 9 26 83 180 1967 19960
一些结果:
{{1}}