今天复习了二叉搜索树的创建,二叉树的前、中、后序遍历递归与非递归的实现,按层遍历等等。其中较难的是二叉树的后序遍历过程
因此单独拿出来详细分析一下过程,以及在这个过程中我踩得一些坑
/**
* 后序非递归遍历
* @param root
*/
/**
* 思路:首先要搞清楚什么时候才能输出根节点的值,必须等到左节点和右节点都访问完的情况才能访问根节点
* 因此,访问根节点的情况有两种:
* 一、当前节点的左右子树都为null时,可以直接访问根节点
* 二、当前节点的左右子树都访问过时,则可以直接访问根节点
* 则可以设置一个标志,让他标识上一个访问的结点
* 遍历栈时,得到栈顶元素,判断他的左右子树为空或者pre标志是否等于当前结点的左右孩子的其中一个时,
* 当这两种情况满足其中一种,则就可以访问当前根节点。
*
* 至于为什么要判断pre标志是否等于当前结点的左右孩子的其中一个,而不是判断它是否等于当前结点的右孩子?
* 原因是这样的:因为可能存在这样一种情况,当前结点只有左孩子结点,则如果去判断它是否等于当前结点的右孩子结点
* 得到的一定是false,这样当前结点永远都不会被访问,并且会陷入死循环,左孩子一直循环入栈的情况。当根结点左
* 子树访问完,如果存在右子树,则会从栈顶得到右子树结点,而此时pre标志等于根节点的左子女,因此第二个条件不成立(
* 即pre不会等于根节点右子女的任何一个子女结点)
*
* LinkedList有一个坑:push操作实际掉的addFirst方法,而pop方法实际掉的是removeFirst方法,链表头是栈顶!!并不是链表尾
*/
public static void endPrintTreeNo(TreeNode root) {
if(root==null)return;
LinkedList<TreeNode> stack=new LinkedList<>();
stack.push(root);
TreeNode pre=null,cur=null;
while(!stack.isEmpty()) {
cur=stack.getFirst();
if((cur.left==null&&cur.right==null)||(pre!=null&&(pre==cur.left||pre==cur.right))){
System.out.print(cur.val+" ");
stack.pop();
pre=cur;
} else {
if(cur.right!=null)
stack.push(cur.right);
if(cur.left!=null)
stack.push(cur.left);
}
}
}