我正在使用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));
}
答案 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
以及堆模板函数中的多个位置调用的。”