后序遍历按照“左孩子-右孩子-根结点”的顺序进行访问。
1.递归实现
/**
* 后序遍历
* @param node
*/
public static void postOrderTraverse(Node node) {
if (node == null) return;
postOrderTraverse(node.leftNode);
postOrderTraverse(node.rightNode);
System.out.print(node.data + "\t");
}
2.非递归实现
后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,要保证左孩子和右孩子都已被访问并且左孩子在右孩子前访问才能访问根结点,这就为流程的控制带来了难题。
对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问, 因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就 保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是 否是第一次出现在栈顶。
/**
* 后序遍历 非递归
* 双栈法
* @param root
*/
public static void postOrder2(Node root) {
Stack<Node> stack = new Stack<Node>();
Stack<Node> output = new Stack<Node>();
Node node = root;
while (node != null || !stack.isEmpty()) {
if (node != null) {
stack.push(node);
output.push(node);
node = node.rightNode;
} else {
node = stack.pop();
node = node.leftNode;
}
}
while (output.size() > 0) {
Node n = output.pop();
System.out.print(n.data + "\t");
}
}