假设我有一个使用深度优先搜索遍历的树,并且我遍历它的算法看起来像这样:
algorithm search(NODE):
doSomethingWith(NODE)
for each node CHILD connected to NODE:
search(CHILD)
现在,在许多语言中,递归的最大深度,例如,如果递归深度超过某个限制,那么过程将因堆栈溢出而崩溃。
如何在没有递归的情况下实现此函数,而是使用堆栈?在许多情况下,有很多局部变量;哪里可以存储?
答案 0 :(得分:17)
你改变它以使用这样的堆栈:
algorithm search(NODE):
createStack()
addNodeToStack(NODE)
while(stackHasElements)
NODE = popNodeFromStack()
doSomethingWith(NODE)
for each node CHILD connected to NODE:
addNodeToStack(CHILD)
至于你的第二个问题:
在很多情况下,有很多局部变量;哪里可以存储?
这些确实可以保存在原来的相同位置。如果变量是“doSomethingWith”方法的局部变量,只需将它们移动到那个变量中,然后将其重构为一个单独的方法。该方法不需要处理遍历,只需要处理,并且可以使用它自己的局部变量,只在其范围内工作。
答案 1 :(得分:4)
稍微不同的遍历。
push(root)
while not empty:
node = pop
doSomethingWith node
for each node CHILD connected to NODE:
push(CHILD)
对于相同的遍历,以相反的顺序推送节点。
如果你正在吹嘘你的筹码,这可能无济于事,因为你会打击你的筹码
如果你有nextChild功能,你可以避免推送所有孩子
答案 2 :(得分:2)
Eric Lippert创建了许多有关此主题的帖子。例如,看一下这个: Recursion, Part Two: Unrolling a Recursive Function With an Explicit Stack
答案 3 :(得分:1)
基本上,你新建了自己的堆栈:char a[] = new char[1024];
或类型安全,node* in_process[] = new node*[1024];
并将您的中间值设置为:
node** current = &in_process[0];
node* root = getRoot();
recurse( root, ¤t) ;**
void recurse( node* root, node** current ) ;
*(*current)++ = root; add a node
for( child in root ) {
recurse( child, current );
}
--*current; // decrement pointer, popping stack;
}