这是维基百科为迭代后序树遍历提供的伪代码。
iterativePostorder(node)
parentStack = empty stack
lastnodevisited = null
while (not parentStack.isEmpty() or node ≠ null)
if (node ≠ null)
parentStack.push(node)
node = node.left
else
peeknode = parentStack.peek()
if (peeknode.right ≠ null and lastnodevisited ≠ peeknode.right)
/* if right child exists AND traversing node from left child, move right */
node = peeknode.right
else
visit(peeknode)
lastnodevisited = parentStack.pop()
非常简单,我已经用Java实现了它。但它不起作用,问题是每次访问最左边的叶子并返回其父叶子时,它会在下一次迭代中将左叶子再次添加到堆栈中。这会导致无限循环。我的方法不正确还是维基百科版本错了?
public static List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) return res;
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode lastVisitedNode = null;
TreeNode curr = root;
int i = 0;
while (curr != null || !s.isEmpty()) {
if (curr != null) {
System.out.println("push " + curr.val);
s.push(curr);
curr = curr.left;
} else {
curr = s.peek();
if (curr.right != null && lastVisitedNode != curr.right) {
curr = curr.right;
} else {
res.add(curr.val);
System.out.println("pop " + curr.val);
lastVisitedNode = s.pop();
}
}
System.out.println(s);
System.out.println(res);
if (i>8) break;
else i++;
}
return res;
}
答案 0 :(得分:0)
维基百科版本 错误的原因与您解释的完全相同。
这是一个可能更好的伪代码,来自geeksforgeeks
1.1 Create an empty stack
2.1 Do following while root is not NULL
a) Push root's right child and then root to stack.
b) Set root as root's left child.
2.2 Pop an item from stack and set it as root.
a) If the popped item has a right child and the right child
is at top of stack, then remove the right child from stack,
push the root back and set root as root's right child.
b) Else print root's data and set root as NULL.
2.3 Repeat steps 2.1 and 2.2 while stack is not empty.
您必须添加额外的代码来检查2.1.a中的节点右子节点是否为空。
答案 1 :(得分:0)
wikipedia伪代码没有错。他们使用两个不同的变量:node
和peekNode
,而您只使用curr
。 Node == null
指的是没有剩下左侧分支要探索的情况,因此我们可以停止推送,而是调查堆栈中的下一个元素。您可以恢复使用两个不同的变量,也可以在代码中进行以下修复:
由于每次调查堆栈时都会将curr
重新分配给非空值,因此在访问节点后需要将curr
重置为null。 (因为仍然没有留下分支的状态仍未改变)。
wikipedia伪代码不必执行此操作,因为它们的node
值仍为空。
这是我的代码,它提供了一个完美的答案:
var currentNode = this.root()
var previousNode = null
while(!nodeStack.isEmpty() || currentNode) {
// If there is a node on which the recursive call is made, we have a subtree to explore. If this is null, we have to backtrack and do a callback.
if (currentNode) {
nodeStack.push(currentNode)
previousNode = currentNode
currentNode = currentNode.leftChild
} else {
currentNode = nodeStack.peek()
if (currentNode.rightChild && previousNode != currentNode.rightChild) {
currentNode = currentNode.rightChild
} else {
callback(currentNode)
currentNode = null
previousNode = nodeStack.pop()
}
}
}