【问题标题】:Single 'Heapify' call when removing max and adding a new element c++ std::make_heap删除 max 并添加新元素时的单个“Heapify”调用 c​​++ std::make_heap
【发布时间】:2018-03-09 08:13:30
【问题描述】:

是否可以弹出max,push一个新元素,然后调用push_heap,维护堆,只调用一次bubble down算法?

    // 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());

删除最大值并将新元素推送到堆中是否“安全”?我已经测试过了,似乎是这样。我有理由不这样做吗?

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

【问题讨论】:

  • 最大的元素会不会在前面,导致'pop_back()'不正确?
  • 是的 - 谢谢。我的“测试”有一个我没有看到的额外 pop_heap 语句。

标签: c++ algorithm heap


【解决方案1】:

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

pop_front(不是你所假设的pop_back)确实会从堆中删除最大元素,但不再保证你有一个堆。也就是说,弹出第一个元素有效地将堆 left 子元素移动到根中。如果子节点更大,那么堆属性就会丢失(即使它适用于第一组子节点,它也可能由于数组中的移位而使任何子树无效)。

此外,如果您使用像std::vector 这样的连续容器,那么pop_front(在vector::begin 上调用std::vector::erase)会不幸地花费您O(N) 时间,这会更糟比pop_heap 的 O(log N) 复杂度。

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

最好只有两个 O(log N) 操作。该函数增长如此缓慢,以至于 1000 和 100 万个元素堆之间几乎没有区别。

【讨论】:

    【解决方案2】:

    您所要求的几乎是您帖子正文中链接问题的完全相同。

    // 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 将交换第一个和最后一个值,back 将包含您要删除的最大值。

    【讨论】:

      猜你喜欢
      • 2017-06-27
      • 2012-12-02
      • 1970-01-01
      • 2020-09-05
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-22
      相关资源
      最近更新 更多