STL优先级队列-删除一个项目
我想使用 C++ STL priority_queue 容器适配器实现计时器排队系统。
我的问题是我想偶尔取消计时器,但是没有接口可以让我轻松删除priority_queue中不是顶部项目的项目。
有什么建议吗?
感谢您的帮助。
I want to implement a timer queuing system using the C++ STL priority_queue container adapter.
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.
Any suggestions?.
Thank you for your help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我曾经遇到过完全相同的场景,并执行了以下操作:
Handler
是boost::function
,但也可以是指向接口或函数的指针)boost::function
调用clear()
,如果使用指针,请将其设置为零),1 为了快速找到免费索引,我使用了单独的
std::stack
索引。当添加定时器且堆栈为空时,添加到向量末尾;否则弹出顶部索引并使用它。2 这是将索引推送到空闲索引堆栈时的要点。
整个事情有点棘手且容易出错,特别是当您的计时器回调需要添加或取消计时器时。 这是上面描述的我的取消计时器类的链接,此代码是公共域
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 astd::vector<Handler>
(in my caseHandler
wasboost::function
, but could as well be pointer to interface or function)boost::function
callclear()
, if using pointers, set it to zero)1 To make finding a free index fast, I used a separate
std::stack
of indices. 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
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
恐怕 STL
priority_queue
不提供这样的功能。您可以编写自己的堆类(这并不难)。您甚至可以通过如下肮脏的技巧来使用 std::xxx_heap 函数:这将使您删除 O(log n) 。
I'm afraid STL
priority_queue
doesn't offer such functionality. You can write your own heap class (which is not that hard). You could even use thestd::xxx_heap
functions by dirty tricks like this:which will get you
O(log n)
delete.尽管其他一些答案是这么说的,但可以访问任何标准容器适配器的底层容器,包括
priority_queue
,因为容器是作为名为c
的受保护成员公开的。您可以继承priority_queue
并扩展接口,或者使用肮脏的技巧,例如 此可临时获得对普通priority_queue
的访问权限。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 calledc
. You can either inherit frompriority_queue
and extend the interface, or use dirty tricks such as this to temporarily gain access to a normalpriority_queue
.如果取消计时器经常发生,那么您需要使用一些不同的结构。 std::map 也没有那么糟糕,尽管 delete_min 的成本会上升。
如果取消计时器的情况很少发生,那么将元素标记为已删除(并在 ::pop 期间忽略它)可能会成功。
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.
If canceling a timer happens rarely, then marking the element as deleted (and ignoring it during ::pop) might do the trick.
STL Priority_queue 容器是专门设计的,因此只有顶部项目可以访问,因此如果您需要能够删除非顶部项目,则必须找到不同的类来使用。
The STL priority_queue container is specifically designed so that only the top item is accessible, so if you need to be able to remove non-top items, you're going to have to find a different class to use.
我有同样的要求。如果您可以自由更改容器,则可以解决此问题的一个是 std:: set(不允许重复)或std::multiset。
两者都是有序的,并且可以擦除容器大小对数的元素(详细信息请参阅文档)。
如需在多集中删除的帮助,您可能需要查看 这个。
在做出决定之前,请先了解 std::set 与 std::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.
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.