我正在尝试为游戏引擎设计任务调度程序。任务可以是动画,触发控制器等。
我的问题是选择哪个容器。这个想法是:当您插入新任务时,容器必须重新排序并将任务放在适当的位置。执行后,任务可能会更改并再次安排或删除。这主要是推和弹。
但是,如果可能的话,如果我能随机访问一个元素会很好,但不是很重要。无论容器是否支持具有相同密钥的一个或多个元素。
我认为优先级队列符合我的需求,但我看到它基于矢量实现,我认为这个容器必须以某种方式进行优化以推送和弹出。
评论
答案 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的渐近增长那样伤害你。
如果您将要执行少量不断更改优先级的任务,那么对矢量进行排序可能是合理的,但您希望使用一种排序算法,该算法在列表几乎已排序时效果很好。
虽然调度是一门艺术,但您必须在构建它之后对其进行分析。在这一点上可能有太少的信息。我倾向于优先级队列,但如果性能不足,请记住其他选项。