【发布时间】:2011-06-11 22:12:55
【问题描述】:
我正在使用优先级队列作为调度程序,但有一个额外的要求。我需要能够取消预定的项目。这相当于从优先级队列的中间移除一个项目。
我不能使用std::priority_queue,因为对除 top 之外的任何元素的访问都是受保护的。
我正在尝试使用algorithm 的堆函数。但我仍然缺少我需要的那块。当我从堆中间删除一个元素时,我希望它能够有效地重建自己。 C++ 提供了这些堆函数:
-
std::make_heapO(3n) -
std::push_heapO(lg(n)) -
std::pop_heapO(2 lg(n))
我想要一个像 std::repair_heap 这样的新函数,带有一个大 O 3n。我会向它提供被取消项目所在的洞的位置,它会正确调整堆。
不提供std::repair_heap 函数似乎是一个巨大的疏忽。我错过了什么明显的东西吗?
是否有提供符合 stl 的 std::repair_heap 的库?
是否有更好的数据结构来建模调度程序?
注意:
我没有使用std::map 有几个原因。
- 堆具有恒定的内存开销。
- 堆具有出色的缓存局部性。
【问题讨论】:
-
如果我错了请纠正我,但我认为您必须为此致电
std::make_heap,因为无论如何您都必须移动元素。 -
我可以使用
std::make_heap。但感觉应该有一个更快的选择。我怀疑repair_heap可以写成O(lg(n)),比如push 和pop。我的推理是repair_heap只是从堆的中间而不是头部弹出。 -
这确实很挑剔,但是虽然说 O(3n) 或 O(2 lg n) 在技术上是正确的,但通常不会这样做,因为它忽略了大 O。 Big-O 在不考虑常数的情况下对相对增长率进行分类。不用写 O(3n),只写 O(n)。同样,不要写 O(2 lg n),写 O(lg n)。现在,如果您确实想说您的代码最多运行 2 次 lg n 比较,那很好 - 直接说出来,不要使用 big-O 表示法。
-
@templatetypedef,在这种情况下,OP实际上只是采用cplusplus.com's的方式来解释他们的算法的时间复杂度,所以我们不应该为此责备OP。
-
@Richard 查看您链接的页面,它说“在第一个和最后一个之间的距离的三倍内达到线性。”这与说 O(3n); 不一样;其中第一个是一个非常具体的界限,没有渐近指定,而第二个在技术上是正确的,但具有误导性。
标签: c++ data-structures stl priority-queue