std :: heap __adjust_heap函数如何工作?

时间:2017-09-18 14:26:28

标签: c++ c++11

我正在使用std :: priority_queue,我试图了解pop函数如何工作以了解每次pop调用中发生了多少次比较。我已经看到优先级队列基于std :: heap。具体来说,pop函数正在使用__adjust_heap函数。我试图理解这个功能但是我遇到了逻辑部分的困难。

我知道在标准的pop_heap函数中,顶部对象被移除,然后最后一个被移到顶部并与其两个子节点进行比较。但在这段代码中似乎并非如此。

有人可以帮助我了解它在这里是如何运作的吗?

__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),
           __gnu_cxx::__ops::__iter_comp_val(__comp));
}

格式化以提高可读性:

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) = std::move(*(first + secondChild));
        holeIndex = secondChild;
    }

    if ((len & 1) == 0 && secondChild == (len - 2) / 2) {
        secondChild = 2 * (secondChild + 1);
        *(first + holeIndex) = std::move(*(first + (secondChild - 1)));
        holeIndex = secondChild - 1;
    }

    std::push_heap(first, holeIndex, topIndex, std::move(value), gnu_cxx::ops::iter_comp_val(comp));
}

2 个答案:

答案 0 :(得分:3)

标准规定比较次数最多为log(N),其中N是堆的大小。

参见例如http://en.cppreference.com/w/cpp/algorithm/push_heap

您列出的辅助函数仅是一个实现细节(正如您从__前导名称中所看到的)

答案 1 :(得分:0)

我没有详细分析该功能,但是在this book,第201页中找到了对此功能的简短描述:

“模板函数Adjust_heap沿堆向下渗透一个孔,直到它没有子代为止。然后,它调用Push_heap对整个堆向上的孔进行渗透,以将其堆回到适当的位置以存储指定的值。 {1}}是从模板函数Adjust_heap以及堆模板函数中的多个位置调用的。”