如何将递归函数转换为使用堆栈?

时间:2010-08-02 19:59:33

标签: algorithm recursion stack

假设我有一个使用深度优先搜索遍历的树,并且我遍历它的算法看起来像这样:

algorithm search(NODE):
  doSomethingWith(NODE)
  for each node CHILD connected to NODE:
    search(CHILD)

现在,在许多语言中,递归的最大深度,例如,如果递归深度超过某个限制,那么过程将因堆栈溢出而崩溃。

如何在没有递归的情况下实现此函数,而是使用堆栈?在许多情况下,有很多局部变量;哪里可以存储?

4 个答案:

答案 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, &current) ;**

void recurse( node* root, node** current ) ;
  *(*current)++ = root; add a node
  for( child in root ) {
    recurse( child, current );
  }
  --*current; // decrement pointer, popping stack;
}