删除max并添加新元素时单个'Heapify'调用c ++ std :: make_heap

时间:2017-09-27 18:18:22

标签: c++ algorithm heap

是否可以弹出最大值,推送一个新元素,然后调用push_heap,维护堆并只调用一次冒泡算法一次?

    // What I think is correct:
    heap.push_back(new_element);
    std::push_heap(heap.begin(), heap.end());
    std::pop_heap(heap.begin(), heap.end());
    heap.pop_back();

    // What I hope is correct:
    heap.pop_back();        
    heap.push_back(new_element);
    std::push_heap(heap.begin(), heap.end());

删除max并将新元素推送到堆是否“安全”?我测试了它,似乎是这种情况。我不应该这样做吗?

非常相关的问题: How to change max element in a heap in C++ standard library?

2 个答案:

答案 0 :(得分:2)

在通过make_heap创建的最大堆中,最大元素将位于前面,并且删除它的适当方式是使用std::pop_heap,句点。

pop_front(不是你假定的pop_back)确实会从堆中删除最大元素,但不再保证你有堆。也就是说,弹出第一个元素可以有效地将堆 left 子项移动到根目录中。如果 right 子项较大,则堆属性将丢失(即使它适用于第一组子项,也可能因为数组中的移位而使任何子树无效)。

此外,如果您使用的是std::vector之类的连续容器,那么pop_front(在std::vector::erase上调用vector::begin)不幸会花费您O( N)时间,比pop_heap的O(log N)复杂度差得多。

您可能(过早地)优化的一种情况是,如果您只是想将交换最大元素与另一个至少与现有最大元素一样大的元素,或者失败, > =最大元素的最大子元素。在这种情况下,您可能会达到O(1)复杂度,但在一般情况下这不太可能。

最好只进行两次O(log N)操作。函数增长得如此之慢,以至于1000到100万个元素堆之间几乎没有差异。

答案 1 :(得分:0)

您要查询的内容几乎与帖子正文中链接的问题完全相同。

if cv2.waitKey(25) & 0xFF == 27:
  break

由于// Precondition is that v is already a heap. int get_max_element_add_new (std::vector<int> &v, int value) { v.push_back(value); std::pop_heap(v.begin(), v.end()); value = v.back(); v.pop_back(); return value; } 将交换第一个和最后一个值,因此pop_heap将包含您要删除的最大值。