刷刷刷 Day 14| 二叉树的遍历

144. 二叉树的前序遍历

LeetCode题目要求

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
示例

图
输入:root = [1,null,2,3]
输出:[1,2,3]
解题思路

最重要的要明白什么是二叉树的前序遍历:即从中间节点开始到左节点再到右节点的遍历过程,可简称为【中左右】遍历
如下图标识的遍历过程,在过程中下面指向的 null ,就是说明到子节点了,如果这是我们知道左节点到了子节点,那就要从右节点开始。

图

上代码,递归实现

class Solution {

    public List<Integer> preorderTraversal(TreeNode root) {
        // 前序遍历即:从中间节点开始到左节点再到右节点的遍历过程,可简称为【中左右】遍历
        
        // 用 List 来存储遍历的结果
        List<Integer> res = new ArrayList<>();
        preorder(root, res);

        return res;
    }

    public void preorder(TreeNode curr, List<Integer> res) {
        // 1、先拿中节点,
        // 2、判断左节点,如果左不为空,那么又作为新的中节点,重复 1、2,直到节点为空
        // 3、判断右节点,如果右不为空,那么又作为新的中节点,重复 1、3,直到节点为空

        if (curr == null) {
            return;
        }

        res.add(curr.val);
        preorder(curr.left, res);
        preorder(curr.right, res);
    }
}

上代码,迭代实现

class Solution {

    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();

        if (root == null) {
            return res;
        }

        // 通过栈来实现,将二叉树的以 中右左的顺序 压入栈中,出栈时的顺序才是中左右 
        Deque<TreeNode> stack = new ArrayDeque<>();
        stack.push(root);

        // 开始遍历栈,如果栈不为空,就先出栈
        while (!stack.isEmpty()) {
            TreeNode curr = stack.pop();
            res.add(curr.val);

            if (curr.right != null) stack.push(curr.right);
            if (curr.left != null) stack.push(curr.left);
        }
        return res;
    }
}

145. 二叉树的后序遍历

LeetCode题目要求

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。
示例

图
输入:root = [1,null,2,3]
输出:[3,2,1]
解题思路

最重要的要明白什么是二叉树的后序遍历:即从左节点开始到右节点再到中间节点的遍历过程,可简称为【左右中】遍历
如下图标识的遍历过程,总是从最左节点开始的。

图

上代码,递归实现

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        // 存储结果
        List<Integer> res = new ArrayList<>();
        postorder(root, res);
        return res;
    }

    public void postorder(TreeNode node, List<Integer> res) {
        if (node == null) {
            return;
        }

        // 从左节点开始递归,这里从root 开始一直到最左子节点,才能继续找右节点,但是右节点为空,那么就把当前左节点的值放入结果
        postorder(node.left, res);
        // 从右节点开始递归
        postorder(node.right, res);
        // 将当前节点值放入结果集
        res.add(node.val);
    }
}

上代码,迭代实现

class Solution {

    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();

        if (root == null) {
            return res;
        }

        Deque<TreeNode> stack = new ArrayDeque<>();
         
        // 后序遍历: 左右中,  前序遍历的顺序是 中左右,
        // 那么可以在入栈时调整顺序变成 中左右,出栈顺序为 中右左, 然后再反转结果就是我们需要的
        stack.push(root);

        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            res.add(node.val);
            if (node.left != null) stack.push(node.left);
            if (node.right != null) stack.push(node.right);
        }

        Collections.reverse(res);
        return res;
    }
}

94. 二叉树的中序遍历

LeetCode题目要求

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例

图
输入:root = [1,null,2,3]
输出:[1,3,2]
解题思路

最重要的要明白什么是二叉树的中序遍历:即从左节点开始到中间节点再到右节点的遍历过程,可简称为【左中右】遍历
如下图标识的遍历过程,总是从最左节点开始的。

图

上代码,递归实现

class Solution {

    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        inorder(root, res);
        return res;
    }

    public void inorder(TreeNode node, List<Integer> res) {
        if (node == null) {
            return;
        }
        // 左中右
        inorder(node.left, res);
        res.add(node.val);
        inorder(node.right, res);
    }
}

上代码,迭代实现

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (root == null) {
            return res;
        }

        Deque<TreeNode> stack = new ArrayDeque<>();
        TreeNode node = root;
        while (node != null || !stack.isEmpty()) {
            // 中序遍历的为 左中右,使用栈时,入栈时,从根一直遍历左节点,都入栈
            if (node != null) {
                stack.push(node);
                node = node.left;
            } else {
                // 当上面的操作左节点都入栈后,此时栈不为空,开始出栈操作,就是左节点出栈并将其值入结果集,同时取右节点
                node = stack.pop();
                res.add(node.val);
                node = node.right;
            }
        }

        return res;
    }
}
重难点

对于递归遍历来说,遍历二叉树代码写起来比较容易,但是递归的过程需要重点理解下。
而对于迭代法来说,弄明白入栈与出栈的过程就基本可以明白,可以通过模拟过程来理解,而中序遍历与前、后序遍历不太一样,需要着重理解了。

附:学习资料链接

posted @ 2023-01-20 17:43  blacksonny  阅读(20)  评论(0编辑  收藏  举报