我给了这样一棵树:
http://www.seqan.de/dddoc/html/streePreorder.png http://www.seqan.de/dddoc/html/streePreorder.png
我可以使用下一个运算符访问每个节点。
// postorder dfs
Iterator< Index<String<char> >, BottomUp<> >::Type myIterator(myIndex);
for (; !atEnd(myIterator); goNext(myIterator))
// do something with myIterator
但我想在树上使用递归算法 有没有办法可以使递归算法(在每个节点上排除最大的子树)迭代? 或者我如何非递归地访问元素?
修改:
实际问题:
我给出了一个递归算法,适用于树。 (递归)
我还使用了一个库,我只能用迭代器访问Items(非标准,迭代)
递归&lt; - &gt;迭代。
我该如何解决这个问题?
答案 0 :(得分:2)
您可以借助堆栈将那个递归函数转换为迭代函数。
//breadth first traversal pseudo-code
push root to a stack
while( stack isn't empty )
pop element off stack
push children
perform action on current node
取决于您想要遍历节点的方式,实现方式会有所不同。所有递归函数都可以转换为迭代函数。关于如何获取特定问题的信息的一般用法。使用堆栈/队列并转换为for循环是应该解决大多数情况的常用方法。
你还应该研究尾递归以及如何识别它们,因为这些问题很好地转化为for循环,许多编译器甚至会为你做这个。
recurrence relations可以解决一些更加数学化的递归调用。您遇到这些尚未解决的可能性不大可能,但您可能会感兴趣。
//编辑,表现? 真的取决于您的实现和树的大小。如果你的递归调用有很多深度,那么你将获得堆栈溢出,而迭代版本将表现良好。我会更好地掌握递归(如何使用内存),你应该能够决定哪种更适合你的情况。 Here is an example of this type of analysis with the fibonacci numbers
答案 1 :(得分:1)
任何递归函数也可以使用堆栈实现。如果这是你要问的问题。
这是关于这个主题的article by Phil Haack。
性能增益的一种方式或另一种方式是推测性的,编译器使用我们在幕后无法始终预测的代码来完成任务。实现两者并得到一些实数。如果它们相似,请使用您认为更具可读性的那个。
答案 2 :(得分:1)
如果您的迭代器仅支持向前(可能是向后)遍历,但不支持树上的链接或快速随机访问,那么您将很难适应树算法。但是,最后任何答案都将取决于您未提供的自定义迭代器提供的界面。
例如,考虑树搜索的简单算法。如果迭代器给出的唯一操作是“从第一个元素开始并逐个移动”,那么显然无法有效地实现树搜索。你也不能实现二进制搜索。因此,您必须提供确切支持哪些操作的列表,以及(严格地说)每个操作的复杂性限制。
答案 3 :(得分:0)
即使使用递归迭代,您最终也会获得每节点节点访问。
你需要知道的是:我的迭代器如何被告知深度优先,然后:我将如何通知一个级别已经开始/结束(即递归步骤的开始/结束)。 / p>
这些知识可以映射到递归算法上。