我找到了这个链接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());
}
}
答案 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是一个返回,而堆栈维护所有每个函数调用的参数和局部变量。堆栈顶部的元素始终表示当前正在执行的函数。