二叉树的遍历

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();
        }
    }
相关推荐
罗西的思考9 小时前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
CSharp精选营11 小时前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
美团技术团队12 小时前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
像我这样帅的人丶你还13 小时前
Java 后端详解(四):分页与搜索
java·javascript·后端
她的男孩13 小时前
数据权限为什么不能只靠注解?Forge 的 Mapper 层 SQL 改写源码拆解
java·后端·架构
tntxia14 小时前
Mybatis的日志输入
java
亦暖筑序15 小时前
Java 8老系统Browser Agent实战:三层拦截把AI操作后台变成可审计流程
java·后端·设计模式
用户2986985301418 小时前
Java 实现 Word 文档加密与权限解除
java·后端
Yeats_Liao19 小时前
14:Servlet中的页面跳转-Java Web
java·后端·架构
未秃头的程序猿19 小时前
告别"if-else地狱"!Java 21模式匹配,代码优雅了10倍
java·后端·面试