需要一些建议来选择合适的容器

时间:2011-06-02 14:24:48

标签: c++ stl

我正在尝试为游戏引擎设计任务调度程序。任务可以是动画,触发控制器等。

我的问题是选择哪个容器。这个想法是:当您插入新任务时,容器必须重新排序并将任务放在适当的位置。执行后,任务可能会更改并再次安排或删除。这主要是推和弹。

但是,如果可能的话,如果我能随机访问一个元素会很好,但不是很重要。无论容器是否支持具有相同密钥的一个或多个元素。

我认为优先级队列符合我的需求,但我看到它基于矢量实现,我认为这个容器必须以某种方式进行优化以推送和弹出。

评论

6 个答案:

答案 0 :(得分:7)

答案 1 :(得分:3)

priority queue似乎是您的最佳选择。

正如您所看到的,pop函数具有恒定的复杂性,push函数在时间上是对数的。

答案 2 :(得分:2)

std :: vector非常适合这个任务,特别是如果容器的“稳态”大小保持相当稳定(队列中的许多任务没有太大差别)。

如果你需要一个可更新的队列(并且std :: priority_queue不是),我建议你使用d_ary_heap_indirect(可以在Boost.Graph“detail”文件夹中找到)。这是一个优先级队列,用于需要可更新优先级队列的Dijkstra和A *算法。无论如何,随机访问是必要的。此外,使用间接使得从队列中插入和删除非常有效。最后,您可以选择容器(作为模板参数),但必须是随机访问(因此,您可以尝试使用vector或deque)。 Pop是常量时间,推送和/或更新是日志时间,正确选择容器会使容器插入常量 - 摊销(并且d_ary_heap_indirect也会第二次摊销,所以我不担心这个) 。

答案 3 :(得分:1)

矢量针对一端的推送和弹出进行了优化。 : - )

要确定优先顺序,您必须对任务进行排序。如果对象的数量相当小,矢量也不是那么糟糕,即使它意味着在排序过程中复制对象。

其他容器(如链表)则需要为每个对象分配一个新节点。

答案 4 :(得分:1)

您可以使用std::priority_queue指定所需的容器类型。 但是:你存储指针(我猜,因为它听起来像你是什么 多态和有身份),所以复制很便宜。你正在管理它 作为一个堆(这是std::priority_queue所做的),所以插入完成 使用push_back和多次交换(lg(n)max)。我什么也看不见 甚至考虑另一种结构而不是std::vector

std::priority_queue会隐藏所有直接访问操作符(例如 operator[])。它这样做是因为如果你修改一个条目,你就是 可能使堆无效(这是类的类不变量)。 但是,如果您确实希望提供直接读取访问权限,则需要提供 容器只有protected,而不是private,因此您可以从中获取 并添加您想要的运算符。我非常把它限制在const 但是,运营商。

答案 5 :(得分:1)

取决于您多久会添加任务并拉下任务(并且可能会执行它们)以及有多少任务。

如果您要完成大量的小任务,那么优先考虑优先级队列,因为节点分配的成本可能不会像n log n的渐近增长那样伤害你。

如果您将要执行少量不断更改优先级的任务,那么对矢量进行排序可能是合理的,但您希望使用一种排序算法,该算法在列表几乎已排序时效果很好。

虽然调度是一门艺术,但您必须在构建它之后对其进行分析。在这一点上可能有太少的信息。我倾向于优先级队列,但如果性能不足,请记住其他选项。