二叉树的遍历

1.递归版

java 复制代码
    public static class TreeNode{
        public int val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(int val){
            this.val = val;
        }
    }
    // 先序: (根) -> 左 -> 右
    // 中序: 左 -> (根) -> 右
    // 后序: 左 -> 右 -> (根)
    public static void f(TreeNode head){
        if (head == null) {
            return;
        }
        // 1
        f(head.left);
        // 2
        f(head.right);
        // 3
    }
    // 先序遍历,递归
    public static void preOrder(TreeNode head){
        if (head == null) {
            return;
        }
        System.out.println(head.val + " ");
        preOrder(head.left);
        preOrder(head.right);
    }
    // 中序遍历,递归
    public static void inOrder(TreeNode head){
        if (head == null) {
            return;
        }
        inOrder(head.left);
        System.out.println(head.val + " ");
        inOrder(head.right);
    }
    // 后序遍历,递归
    public static void posOrder(TreeNode head){
        if (head == null) {
            return;
        }
        posOrder(head.left);
        posOrder(head.right);
        System.out.println(head.val + " ");
    }

2.非递归版

2.1 先序遍历

java 复制代码
    // 先序打印 非递归
    public static void preOrder(TreeNode head){
        if (head != null) {
            Stack<TreeNode> stack = new Stack<>();
            stack.push(head);
            while (!stack.isEmpty()) {
                head = stack.pop();
                System.out.println(head.val + " ");
                if (head.right != null) {
                    stack.push(head.right);
                }
                if (head.left != null) {
                    stack.push(head.left);
                }
            }
            System.out.println();
        }
    }

2.2中序遍历

java 复制代码
    // 中序打印 非递归
    // 1.子树头、左边界进栈
    // 2.栈弹出一个节点打印,节点右树进栈
    // 3.没有子树且栈空
    public static void inOrder(TreeNode head){
        if (head != null) {
            Stack<TreeNode> stack = new Stack<>();
            while (!stack.isEmpty() || head == null) {
                if (head != null) {
                    stack.push(head);
                    head = head.left;
                }
                else {
                    head = stack.pop();
                    System.out.println(head.val + " ");
                    head = head.right;
                }
            }
            System.out.println();
        }
    }

2.3后续遍历(1)

java 复制代码
    // 后续打印
    // 先序: (根) -> 左 -> 右
    // 先序': (根) -> 右 -> 左
    // 反转: 左 -> 右 -> (根)
    public static void posOrder(TreeNode head){
        if (head != null) {
            Stack<TreeNode> stack = new Stack<>();
            Stack<TreeNode> collect = new Stack<>();
            stack.push(head);
            while (!stack.isEmpty()) {
                head = stack.pop();
                collect.push(head);
                if (head.left != null) {
                    stack.push(head.left);
                }
                if (head.right != null) {
                    stack.push(head.right);
                }     
            }
            while (!collect.isEmpty()) {
                System.out.println(collect.pop().val + " ");
            }
        }
    }

2.4后续遍历(2)

java 复制代码
    public static void posOrderOneStack(TreeNode h){
        if (h != null) {
            Stack<TreeNode> stack = new Stack<>();
            stack.push(h);
            // 如果始终没有打印节点,h就一直是头结点
            // 一旦打印过节点,h就变成打印节点
            // 之后h含义:上一次打印的节点
            while (!stack.isEmpty()) {
                TreeNode cur = stack.peek();
                if (cur.left != null
                    && h != cur.left
                    && h != cur.right) {
                        // 有左树且左树未处理
                    stack.push(cur.left);
                }
                else if (cur.right != null
                        && h != cur.right) {
                        // 有右树且右树未处理
                    stack.push(cur.right);
                }
                else{
                    // 没有左树 右树 或者左树右树都处理了
                    System.out.println(cur.val + " ");
                    h = stack.pop();
                }
            }
            System.out.println();
        }
    }
相关推荐
历程里程碑3 小时前
54 深入解析poll多路复用技术
java·linux·服务器·开发语言·前端·数据结构·c++
靠沿4 小时前
【动态规划算法】专题二——路径问题
算法·动态规划
手写码匠4 小时前
手写 AI 推理加速引擎:从零实现 KV Cache 与 Speculative Decoding
人工智能·深度学习·算法·aigc
无限进步_4 小时前
【C++】可变参数模板与emplace系列
java·c++·算法
一切皆是因缘际会4 小时前
AI Agent落地困局与突破:从技术架构到企业解析
数据结构·人工智能·算法·架构
sheeta19984 小时前
LeetCode 每日一题笔记 日期:2026.05.16 题目:154. 寻找旋转排序数组中的最小值 II
笔记·算法·leetcode
计算机安禾4 小时前
【c++面向对象编程】第28篇:new/delete vs malloc/free:C++中正确动态内存管理
开发语言·c++·算法
qeen874 小时前
【算法笔记】各种常见排序算法详细解析(下)
c语言·数据结构·c++·笔记·学习·算法·排序算法
逐光老顽童4 小时前
Java 内存模型深度解析与 JVM 调优实战指南
java·架构