Java 二叉树遍历:4 种遍历方式 + 记忆口诀,3 分钟秒杀面试

177 阅读2分钟

以下是Java实现二叉树四种遍历方式(前序、中序、后序、层序)的代码,添加了便于快速记忆的注释和口诀:

代码实现(带注释)

import java.util.*;

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public class BinaryTreeTraversal {
    // 前序遍历:根 -> 左 -> 右
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (root == null) return res;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            res.add(node.val);          // 先访问根节点
            if (node.right != null)     // 右子树先入栈(后访问)
                stack.push(node.right);
            if (node.left != null)      // 左子树后入栈(先访问)
                stack.push(node.left);
        }
        return res;
    }

    // 中序遍历:左 -> 根 -> 右
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode curr = root;
        while (curr != null || !stack.isEmpty()) {
            while (curr != null) {      // 先将左子树全部入栈
                stack.push(curr);
                curr = curr.left;
            }
            curr = stack.pop();         // 弹出最左节点
            res.add(curr.val);          // 访问根节点
            curr = curr.right;          // 转向右子树
        }
        return res;
    }

    // 后序遍历:左 -> 右 -> 根
    public List<Integer> postorderTraversal(TreeNode root) {
        LinkedList<Integer> res = new LinkedList<>();
        if (root == null) return res;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            res.addFirst(node.val);     // 逆序添加(根 -> 右 -> 左)
            if (node.left != null)      // 左子树先入栈
                stack.push(node.left);
            if (node.right != null)     // 右子树后入栈
                stack.push(node.right);
        }
        return res;
    }

    // 层序遍历:按层从上到下,从左到右
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null) return res;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            int levelSize = queue.size();
            List<Integer> level = new ArrayList<>();
            for (int i = 0; i < levelSize; i++) {
                TreeNode node = queue.poll();
                level.add(node.val);    // 按顺序访问当前层节点
                if (node.left != null)  // 左子节点入队
                    queue.offer(node.left);
                if (node.right != null) // 右子节点入队
                    queue.offer(node.right);
            }
            res.add(level);             // 添加当前层结果
        }
        return res;
    }
}

记忆口诀

前序遍历

前序遍历很简单,根左右来不反转
栈中先压右子树,左子树后入栈先

中序遍历

中序遍历左根右,左子树全入栈走
弹出节点再转向,右子树重复此流程

后序遍历

后序遍历左右根,逆序添加巧实现
根右左来入栈反,链表头插即完成

层序遍历

层序遍历用队列,根节点先入队列
每层节点依次出,左右子节点再入