二叉树前中后序遍历

发布时间 2024-01-07 11:00:58作者: hexiang|

二叉树深度遍历

中序遍历

public List<Integer> inorderTraversal(TreeNode root) {
    //创建一个答案数组
        List<Integer> ans = new ArrayList<>();
    //创建一个双向链表,用作栈
        Deque<TreeNode> stk = new LinkedList<>();
    //当栈不空或者root不是null时
        while(root != null || stk.isEmpty()){
            //将所有左子节点入栈,找到没有左子树的节点为止
            while(root != null){
                stk.push(root);
                root = root.left;
            }
            //当栈不空时,弹出栈顶元素,该节点就是遍历到的节点,将其加入答案数组,并转向该节点的右子树
            /**
            *分析:为什么直接令root = tmp.right正确
            *1. tmp.right==null时 进入下一个循环时,回直接弹出栈顶
            *元素(该节点的父节点)
            *2. tmp.right!=null时,说明该遍历该节点的右子树了,当
            *右子树遍历完成后,在弹出的节点还是该节点的父节点;
            */
            while (stk.isEmpty()){
                TreeNode tmp = stk.pop();
                ans.add(tmp.val);
                root = tmp.right;
            }
        }
        return ans;
    }

前序遍历

 public List<Integer> preorderTraversal(TreeNode root) {
     //同上
        List<Integer> ans = new ArrayList<>();
        Deque<TreeNode> stk = new LinkedList<>();
     //同上
        while(root != null || !stk.isEmpty()){
            //找到最左节点,不同的是,边找,边将节点加入答案,因为前序遍历就是这样的
            while(root != null){
                stk.push(root);
                ans.add(root.val);
                root = root.left;
            }
            //栈不空,弹出栈顶元素,此时,这个元素已经被遍历过了,我们直接令他等于他的右子树,接着遍历,如果没有右子树的话,进入下一个循环,又会弹出栈顶元素;
            if(!stk.isEmpty()){
                root = stk.pop();
                root = root.right;
            }
        }
        return ans;
    }

后序遍历 重点

public List<Integer> postorderTraversal(TreeNode root) {
    //解法一:利用前序遍历的性质:根->左子树->右子树,可以发现,如何我们将其反转,就变成了右子树-》左子树-》根;和后序遍历很接近,后序遍历:左子树-》右子树-》根;我们只需将前序遍历改为根-》右子树-》左子树;再反转就得到了后序遍历;
        List<Integer> ans = new ArrayList<>();
        Deque<TreeNode> stk1 = new LinkedList<>();
        Deque<TreeNode> stk2 = new LinkedList<>();

        while(root != null || !stk1.isEmpty()){
            while(root != null){
                stk2.push(root);
                stk1.push(root);
                root = root.right;
            }
            if(!stk1.isEmpty()){
                root = stk1.pop();
                root = root.left;
            }
        }
        while (!stk2.isEmpty()){
            ans.add(stk2.pop().val);
        }
        return ans;

    
    //-----------------------------------------------------------------------------------------------------------------
    //解法二:
    //创建答案数组和双向链表栈
        List<Integer> ans = new ArrayList<>();
        Deque<TreeNode> stk = new LinkedList<>();
    //增加一个prev节点,指向上一个遍历到的节点
        TreeNode prev = null;
        if (root == null)
            return ans;

        while(root != null || !stk.isEmpty()){
            //同样的先将左子节点全部入栈
            while(root != null){
                stk.push(root);
                root = root.left;
            }
            //把栈顶元素抛出来
            root = stk.pop();
            //判断这个节点是不是下一个该遍历的节点
            //判断条件是该节点的右子树是不是null或者上一个遍历的节点prev
            //如果是,则将prev指向该节点,并将root指向null(为了下一次循环时直接抛出栈顶元素,避免重复遍			 //历左子树)
            if(root.right == null || root.right == prev){
                ans.add(root.val);
                prev = root;
                root = null;
            }else{
                //如果不是,则将该节点重新入栈,并将root指向其右子树,因为如果其不是的话必定有右子树,且没				//有遍历到;
                stk.push(root);
                root = root.right;
            }
        }
        return ans;