【问题标题】:Removing front element and adding new element to min-heap (std::priority_queue) [duplicate]删除前元素并将新元素添加到最小堆(std::priority_queue)[重复]
【发布时间】:2017-06-27 16:34:54
【问题描述】:

用例:我想为一个 Linux 程序实现一个非常有效的发送队列,该程序在网络测试程序中每秒发送许多速率受限的大量 UDP 数据包流。目前,我使用一个

priority_queue< pair<timespec, int>,
                std::vector<pair<timespec, int>>,
                std::greater<pair<timespec, int>> >

程序运行正常且速度很快。但我希望能够在队列前面弹出并在一个操作中添加一个新元素,即每个 pop/emplace 对只有一个 re-heapify。否则pop会重新heapify,然后emplace会直接re-heapify。

这可以用 std::make_heap、std::push_heap 和 std::pop_heap 完成吗?还是我必须自己动手?我当前的程序确实在 std::priority_queue 上弹出,然后是 emplace,其成本为 '2*O(log(N))'。

FWIW,当前程序在这里:https://github.com/alapaa/timestamping/tree/send_queue

带有队列的实际发送者是这个 src 文件: https://github.com/alapaa/timestamping/blob/send_queue/manysock/sender.cpp

【问题讨论】:

标签: c++ algorithm


【解决方案1】:

使用 deque 作为容器,使用 make_heap 进行堆化。 --> 使用vector作为容器,使用反向迭代器make_heap,并在后面推。 会快一点。

vector<int> v{4,3,7,1,5};
make_heap(v.rbegin(), v.rend(), greater<int>());
for(auto& a : v) cout << a << ' ';
cout << endl;
q.pop_back();
q.push_back(9);
make_heap(v.rbegin(), v.rend(), greater<int>());
for(auto& a : q) cout << a << ' ';
cout << endl;

【讨论】:

  • 在这种特殊情况下,标准是否保证 make_heap 便宜(对数)?我也想避免使用双端队列,我更喜欢矢量来提高速度。 (q 的大小不会随着时间的推移而增加)。我只想把新元素放在向量的前面,然后筛选它,直到我重新建立了 min-heap 属性。也许最好自己动手。
  • 如果我没记错的话,make_heap 与优先级队列中使用的算法相同。所以,如果你打算使用优先队列,没有理由避免使用 make_heap。
  • 但是对于 std::priority_queue,您通常只在开始时调用一次 make_heap(昂贵),然后经常弹出和推送元素(推送和弹出是对数)。
  • 我想说的是,使用pri队列的成本比使用make_heap要多。
  • 为什么? std pri q 只是 make_heap、push_heap 和 pop_heap 的适配器/包装器。并且算法复杂度应该是堆中的。
【解决方案2】:

很抱歉回答我自己的问题,但我在之前对 SO 的搜索中没有找到这个解决方案(查看 jxh:s 答案):How to change max element in a heap in C++ standard library?

【讨论】:

  • 如果另一个问题提供了您问题的答案,那么正确的方法是将您的问题标记为另一个问题的duplicate。不要发布带有链接的答案。我已经投票了。
猜你喜欢
  • 2019-04-26
  • 1970-01-01
  • 2018-06-14
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
相关资源
最近更新 更多