package com.camnter.basicexercises.tree; import com.camnter.basicexercises.core.TreeNode; import java.util.Stack; /** * 后续遍历 *

* 左右根 *

*

* - 1 * - 2 3 * - 4 5 6 * - 7 8 *

* 4 7 8 5 2 6 3 1 *

* 后序遍历的非递归实现:对于任一结点 P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能 * 将其出栈并访问,因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可 * 以将其出栈并访问。这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因 * 此需要多设置一个变量标识该结点是否是第一次出现在栈顶 * * @author CaMnter */ public class PostOrder { void postOrder(TreeNode root) { if (root == null) return; TreeNode current = root; // 设置一个标记结点,用来确定是第几次访问栈顶元素 // 主要用于标记一个 节点 的 right 节点是否输出了,用于判断是否要输出当前节点 TreeNode flag = null; Stack> stack = new Stack>(); while (current != null || !stack.isEmpty()) { if (current != null) { // 有左,处理左 stack.push(current); current = current.left; } else { // 无左 尝试找右 current = stack.peek(); // 判断栈顶元素是否是第一次出现,以压入其右子树 if (current.right != null && current.right != flag) { // 无左,处理上一个节点的右,再指向左 current = current.right; stack.push(current); // return to left current = current.left; } else { // 无左,处理上一个节点的右,没有上一个节点的右,就打印,同时 flag 标记 该节点 // 然后标记 current 为 null,再次执行 无左 尝试找右 current = stack.pop(); // print System.out.print(current.value + " "); flag = current; current = null; } } } } public static void main(String args[]) { PostOrder postOrder = new PostOrder(); postOrder.postOrder(TreeNode.getTree()); } }