树状排队

时间:2010-03-12 06:01:32

标签: c++ language-agnostic data-structures queue

我正在实现类似解释器的项目,我需要一个奇怪的小调度队列。因为我想尝试避免轮子改造,所以我希望有人可以给我类似结构或现有工作的参考。我知道我可以简单地实例化多个队列,我只是寻找其他可能比我有更好想法的人的观点;)

我设想它可能会像这样工作:结构是一个单根的树。你得到一种“insert_iterator”到根,然后将元素推到它上面(例如下面例子中的a和b)。但是,您可以随时将迭代器拆分为多个迭代器,从而有效地创建分支。分支不能再次合并到单个队列中,但是您可以从队列的前面开始弹出元素(再次使用一种“visitor_iterator”),直到可以丢弃空分支(由您自行决定)。

            x -> y -> z
a -> b -> { g -> h -> i -> j }
            f -> b

有什么想法吗?看起来像一个相对简单的结构,使用队列池实现自己,但我遵循“先思考,后来编码”的策略:)

由于

编辑:我想我会添加一些额外的背景信息。这与问题无关,但我认为这可能有助于澄清我的目标。这个结构背后的想法非常粗略,它主要用于调度计算......分支可以以COMMIT或ROLLBACK结束。如果x - >中的任何一个...,g - > ...或f - > ...以COMMIT结束,然后

a -> b

按顺序执行,以及以COMMIT结尾的分支执行。 E.g。

x -> y -> z -> COMMIT

然而,a - > b仅在至少一个分支被提交时才执行一次。 如果所有三个分支以ROLLBACK结束,则丢弃整个树,包括初始事件a - >湾

感谢迄今为止的精彩答案!我一回到家,就会详细检查它们。

5 个答案:

答案 0 :(得分:2)

Boost Graph Library包含一个称为不相交集的数据结构,它在此模拟您需要的结构(一组相互关联的集合)。

另一种思考这种数据结构的方法是作为森林。森林是一个不相交的树木联盟。

答案 1 :(得分:0)

我认为结构 Tree,但不是平衡或二进制。如果您想要完全控制添加新节点的方式,那么您必须指定完成的方式,例如: a.addSibling(b)

由于这是为了安排,我猜测应该大致同时访问兄弟姐妹。您的访问者不必回溯,而是必须为您分支的地方产生其他访问者。所以pop的第三个元素是x,g f。

可能会帮助您查看JGraphT

答案 2 :(得分:0)

对我而言,它看起来更像是一棵树(一般的,不是二进制的),而不是一个队列。删除节点的语义需要明确定义。

顺便说一下,提及“调度队列”也为Priority Queue敲响了响铃。

答案 3 :(得分:0)

K,我非常认真地看了所有给出的答案,尤其是Quicksilver提出的不相交集的提升实施。 (在此处找到了一些其他参考:http://en.wikipedia.org/wiki/Disjoint-set_data_structure和此处:http://www.boost.org/doc/libs/1_42_0/libs/disjoint_sets/disjoint_sets.html)。

然而,我得出的结论是,虽然我的数据结构确实是其他人建议的树,但结构的算法要求更好地匹配队列的算法要求。我将使用的主要操作是push_front和pop_back,而我不需要搜索,合并等。因此,我觉得在这种情况下,在它们上面定义了“索引树”的队列池将更好地为我服务。

假设我以从左到右,从上到下的顺序将所有元素插入到队列中,那么单个队列可以很好地工作,因为我将从树的“根”弹出并推到结束缓冲。但是,一旦我弹出了元素的根字符串,那么我开始“弹出”的下一个分支将不一定是内存中的下一个。同样,如果我回滚一个分支,那么它不一定在缓冲区的末尾。这两种情况显然都会在记忆中留下空白。因此,简单队列上的更复杂的索引结构可能会起作用,但我怀疑这可能不值得。

所以现在我赞成一个队列池的简单想法。一旦需要新队列,从池中选择它或者如果没有可用则创建一个新队列,然后将其添加到树中。如果队列为空,则将其返回池并删除树节点。池本身就是一个优先级队列,前面分配的缓冲区最大,后面区分的缓冲区最小。一段时间后,很少或根本没有分配新的内存(假设发生的“弹出”量与“推”的数量大致相同;))

感谢您提出的所有建议,如果您对此策略有其他意见,请随时发表评论 - 我会投票给任何看似有用的内容。

答案 4 :(得分:0)

你说,

  

x - > y - > z - > COMMIT

并且它还可以指树状队列,其包括多个N的y,状态/数据检查集并且从顶部(z)执行,但是从底部(x)接收状态变化。

x[N]("data check") -> x[N-1]("data check") -> x[N-2]("data
     

检查“) - >检查 - > y->检查 - >   y-> state - > z - >检查 - > z-> state - > Z->提交

似乎很难支持这种结构,如果队列是从较小到较大的任务编码,从x到z,但最后,你是否真的以这种方式实现了它?

对我来说(我的类似问题What are patterns/types of task queues? Can the multi-level task queue exist in form of a N-tree?)似乎是一个N级结构,遍历每个级别有三种状态机的子节点:$ me-> tryCommit(tryAdvanceChildsBelow(tryAdvanceToNextSiblingStep) (getNextSibling()))和一个要重写的混乱实现。