后序使用尾递归

时间:2011-03-27 15:50:12

标签: algorithm tail-recursion

我找到了这个链接http://www.experts-exchange.com/Programming/Algorithms/Q_25205171.html,它建议了一种做后序尾递归的方法。但是,它使用2个堆栈,有没有办法只用一个堆栈来做到这一点。谢谢!

下面的

是从上面链接粘贴的java代码:

public static final <T> void postorder(Tree<T> root) {
    Stack<Tree<T>> stack = new Stack<Tree<T>>();
    Stack<Tree<T>> traversal = new Stack<Tree<T>>();
    stack.push(root);
    while (!stack.isEmpty()) {
      Tree<T> node = stack.pop();
      if (node.right != null) 
        stack.push(node.right);
      }
      if (node.left != null) {
        stack.push(node.left);
      }
      traversal.push(node);
    }
    while (!traversal.isEmpty()) {
      System.out.println(traversal.pop().value.toString());
    }
  }

1 个答案:

答案 0 :(得分:1)

是的,但代码需要采用不同的结构。对递归算法进行适当的基于堆栈的仿真应该保持堆栈上的节点,直到节点及其子节点完全遍历为止。堆栈应该包含一个类的实例,该类包含有关遍历了多少个子项的信息,例如:

public class StackElement<T> {
    public Tree<T> node;
    public int numTraversedChildren;
}

(为简单起见,使用公共字段)。无论何时将节点推入堆栈,请推送引用该节点的StackElement numTraversedChildren为0.在循环的顶部,查看(不要弹出)堆栈以查找顶级元素。当且仅当numTraversedChildren == 2时,您知道已遍历此节点的所有子节点。在这种情况下,您可以处理(在您的情况下,打印)该节点,然后弹出它。否则,将节点保持在堆栈上,递增numTraversedChildren,并推送其左子节点(如果numTraversedChildren的旧值为0)或其右子节点(如果旧值numTraversedChildren是1)。

注意,当遵循这种方法时,while循环和堆栈上的推/弹操作有效地模拟函数调用:push是一个调用,pop是一个返回,而堆栈维护所有每个函数调用的参数和局部变量。堆栈顶部的元素始终表示当前正在执行的函数。