我想使用C ++ STL priority_queue容器适配器实现定时器排队系统。
我的问题是我偶尔会取消一个计时器,但是没有接口可以让我轻松删除priority_queue中不是顶级项目的项目。
有什么建议吗?。
感谢您的帮助。
答案 0 :(得分:10)
我有一次完全相同的情况并做了以下事情:
std::priority_queue
中保留的结构只包含排序时间和std::vector<Handler>
的索引(在我的情况下Handler
是boost::function
,但也可以是指向界面或功能的指针)boost::function
调用clear()
,如果使用指针,则将其设置为零) 1 为了快速找到一个免费索引,我使用了一个单独的std::stack
索引。添加计时器并且该堆栈为空时,在向量的末尾添加;否则弹出顶部索引并使用它。
2 这是将索引推送到自由索引堆栈时的重点
整个过程有点棘手且容易出错,特别是如果您的计时器回调需要添加或取消计时器。 Here's a link to my canceling timer class described above, this code is public domain
答案 1 :(得分:7)
我担心STL priority_queue
不提供此类功能。您可以编写自己的堆类(这并不难)。您甚至可以通过这样的脏技巧使用std::xxx_heap
函数:
delete_heap(iterator to_delete, iterator heap_begin, iterator heap_end)
{
to_delete->key = something that would compare less to everything; // make sure it gets to the top in the next step
std::push_heap(heap_begin, to_delete+1);
std::pop_heap(heap_begin, heap_end);
}
会让你O(log n)
删除。
答案 2 :(得分:4)
尽管其他一些答案说,但是可以访问任何标准容器适配器的基础容器,包括priority_queue
,因为容器是作为名为c
的受保护成员公开的。您可以继承priority_queue
并扩展界面,也可以使用this之类的肮脏技巧暂时获得正常priority_queue
的访问权限。
答案 3 :(得分:3)
我的问题是我偶尔会取消一个计时器,但是没有接口可以让我轻松删除priority_queue中不是顶级项目的项目。
如果经常取消定时器,那么您需要使用一些不同的结构。虽然delete_min的成本会上升,但std :: map也不是那么糟糕。
如果很少取消定时器,那么将元素标记为已删除(并在:: pop期间忽略它)可能会有效。
答案 4 :(得分:2)
STL priority_queue容器是专门设计的,因此只能访问顶级项目,因此如果您需要能够删除非顶级项目,则必须找到要使用的其他类。
答案 5 :(得分:0)
我有同样的要求。如果您可以自由更改容器,则可以解决此问题的是std::set(不允许重复)或std::multiset。
两者都是有序的,可以删除容器大小的对数元素(有关详细信息,请参阅文档)。 有关在多集中删除的帮助,您可能希望看到this。
在决定之前查看差异std::set vs std::priority_queue。