繁体   English   中英

STL优先级队列 - 删除项目

[英]STL Priority Queue - deleting an item

我想使用C ++ STL priority_queue容器适配器实现计时器排队系统。

我的问题是我偶尔会取消一个计时器,但是没有接口可以让我轻松删除priority_queue中不是顶级项目的项目。

有什么建议么?。

谢谢您的帮助。

我有一个完全相同的场景,并做了以下事情:

  • 我在std::priority_queue中保存的结构只包含排序时间和std::vector<Handler>的索引(在我的情况下, Handlerboost::function ,但也可以是指向接口或函数的指针)
  • 添加计时器时,我会在处理程序1的向量中找到一个自由索引,并将处理程序存储在该索引处。 将索引和时间存储在priority_queue中。 将索引作为标记返回给客户端以取消
  • 取消定时器,传递添加时收到的索引。 清除该索引处的处理程序(对于boost::function调用clear() ,如果使用指针,则将其设置为零)
  • 当回调计时器时,从优先级队列中获取其处理程序索引并检查处理程序向量 - 如果该位置的处理程序为空()/ NULL,则计时器已被取消。 将处理程序索引标记为free 2

1为了快速找到一个自由索引,我使用了一个单独的std::stack索引。 添加计时器并且该堆栈为空时,在向量的末尾添加; 否则弹出顶部索引并使用它。

2这是将索引推送到自由索引堆栈时的要点

整个过程有点棘手且容易出错,特别是如果您的计时器回调需要添加或取消计时器。 这是我上面描述的取消计时器类的链接,此代码是公共域

我担心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)删除。

尽管其他一些答案说,但是可以访问任何标准容器适配器的底层容器,包括priority_queue ,因为容器是作为受保护的成员c公开的。 您可以从继承priority_queue和扩展接口,或使用下三滥的手段,如这种暂时获得正常priority_queue

我的问题是我偶尔会取消一个计时器,但是没有接口可以让我轻松删除priority_queue中不是顶级项目的项目。

如果经常取消定时器,那么您需要使用一些不同的结构。 尽管delete_min的成本会上升,但std :: map也不是那么糟糕。

如果很少取消定时器,那么将元素标记为已删除(并在:: pop期间忽略它)可能会起作用。

STL priority_queue容器是专门设计的,因此只能访问顶级项目,因此如果您需要能够删除非顶级项目,则必须找到要使用的其他类。

我有同样的要求。 如果您可以自由更改容器,则可以解决此问题的是std :: set (不允许重复)或std :: multiset

两者都是有序的,可以删除容器大小的对数元素(有关详细信息,请参阅文档)。 有关在多集中删除的帮助,您可能希望看到这一点

在决定之前,请查看差异std :: set vs std :: priority_queue

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM