[英]STL Priority Queue - deleting an item
I want to implement a timer queuing system using the C++ STL priority_queue container adapter. 我想使用C ++ STL priority_queue容器适配器实现计时器排队系统。
My problem is that I want to occasionally cancel a timer, however there are no interfaces that enable me to easily delete an item in the priority_queue that is not the top item. 我的问题是我偶尔会取消一个计时器,但是没有接口可以让我轻松删除priority_queue中不是顶级项目的项目。
Any suggestions?. 有什么建议么?。
Thank you for your help. 谢谢您的帮助。
I had the exact same scenario once and did the following: 我有一个完全相同的场景,并做了以下事情:
std::priority_queue
contained only the time to sort by and an index to a std::vector<Handler>
(in my case Handler
was boost::function
, but could as well be pointer to interface or function) 我在std::priority_queue
中保存的结构只包含排序时间和std::vector<Handler>
的索引(在我的情况下, Handler
是boost::function
,但也可以是指向接口或函数的指针) boost::function
call clear()
, if using pointers, set it to zero) 清除该索引处的处理程序(对于boost::function
调用clear()
,如果使用指针,则将其设置为零) 1 To make finding a free index fast, I used a separate std::stack
of indices. 1为了快速找到一个自由索引,我使用了一个单独的std::stack
索引。 When adding a timer and that stack is empty, add at the end of vector; 添加计时器并且该堆栈为空时,在向量的末尾添加; otherwise pop the top index and use it. 否则弹出顶部索引并使用它。
2 Here's the point when you push the index to the free indices stack 2这是将索引推送到自由索引堆栈时的要点
The whole thing is somewhat tricky and error-prone, especially if your timer callbacks need to add or cancel timers. 整个过程有点棘手且容易出错,特别是如果您的计时器回调需要添加或取消计时器。 Here's a link to my canceling timer class described above, this code is public domain 这是我上面描述的取消计时器类的链接,此代码是公共域
I'm afraid STL priority_queue
doesn't offer such functionality. 我担心STL priority_queue
不提供这样的功能。 You can write your own heap class (which is not that hard). 您可以编写自己的堆类(这并不难)。 You could even use the std::xxx_heap
functions by dirty tricks like this: 你甚至可以通过像这样的脏技巧使用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);
}
which will get you O(log n)
delete. 这会让你O(log n)
删除。
Despite what some other answers say, it is possible to access the underlying container of any standard container adapter, including priority_queue
, since the container is exposed as a protected member called c
. 尽管其他一些答案说,但是可以访问任何标准容器适配器的底层容器,包括priority_queue
,因为容器是作为受保护的成员c
公开的。 You can either inherit from priority_queue
and extend the interface, or use dirty tricks such as this to temporarily gain access to a normal priority_queue
. 您可以从继承priority_queue
和扩展接口,或使用下三滥的手段,如这种暂时获得正常priority_queue
。
My problem is that I want to occasionally cancel a timer, however there are no interfaces that enable me to easily delete an item in the priority_queue that is not the top item. 我的问题是我偶尔会取消一个计时器,但是没有接口可以让我轻松删除priority_queue中不是顶级项目的项目。
If canceling a timer happens often, then you need to use some different structure. 如果经常取消定时器,那么您需要使用一些不同的结构。 std::map isn't that bad too, though cost of delete_min would go up. 尽管delete_min的成本会上升,但std :: map也不是那么糟糕。
If canceling a timer happens rarely, then marking the element as deleted (and ignoring it during ::pop) might do the trick. 如果很少取消定时器,那么将元素标记为已删除(并在:: pop期间忽略它)可能会起作用。
STL priority_queue容器是专门设计的,因此只能访问顶级项目,因此如果您需要能够删除非顶级项目,则必须找到要使用的其他类。
I had the same requirement. 我有同样的要求。 If you have the freedom to change the container, the one that can solve this problem is std::set (no duplicates allowed) or std::multiset . 如果您可以自由更改容器,则可以解决此问题的是std :: set (不允许重复)或std :: multiset 。
Both are ordered and can erase an element logarithmic in container size (see the documentation for details). 两者都是有序的,可以删除容器大小的对数元素(有关详细信息,请参阅文档)。 For help in deleting in multi set you might want to see this . 有关在多集中删除的帮助,您可能希望看到这一点 。
See the difference std::set vs std::priority_queue before deciding. 在决定之前,请查看差异std :: set vs std :: priority_queue 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.