算法通关:017_2:二叉树及三种顺序的非递归遍历

文章目录

题目

二叉树及三种顺序的非递归遍历

思路

java 复制代码
import java.util.Stack;

/**
 * @Author: ggdpzhk
 * @CreateTime: 2024-08-04
 * 二叉树非递归版本
 */
public class _017_Tree2 {

    public static void main(String[] args) {
        TreeNode head = new TreeNode(1);
        head.left = new TreeNode(2);
        head.right = new TreeNode(3);
        head.left.left = new TreeNode(4);
        head.left.right = new TreeNode(5);
        head.right.left = new TreeNode(6);
        head.right.right = new TreeNode(7);

        System.out.println("先序遍历非递归版");
        preOrder(head);
        System.out.println();

        System.out.println("中序遍历非递归版");
        inOrder(head);
        System.out.println();

        System.out.println("后序遍历非递归版:两个栈");
        postOrder(head);
        System.out.println();

        System.out.println("后序遍历非递归版:1个栈");
        postOrder2(head);
        System.out.println();
    }


    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode(int x) {
            val = x;
        }
    }

    //先序打印所有节点,非递归版
    public static void preOrder(TreeNode head) {
        if(head != null){
            Stack<TreeNode> stack = new Stack<TreeNode>();
            stack.push(head);
            //压入顺序先右再左  这样弹出顺序就是反的,就是我们要的先序遍历的顺序
            //不懂你就写一遍 这个思路真的很牛
            while(!stack.isEmpty()){
                head = stack.pop();
                System.out.print(head.val + " ");
                if(head.right != null){
                    stack.push(head.right);
                }
                if(head.left != null){
                    stack.push(head.left);
                }
            }
            System.out.println();
        }
    }

    //中序打印所有节点,非递归版
    public static void inOrder(TreeNode head) {
        if(head != null){//这个是root
            Stack<TreeNode> stack = new Stack();
            //下面的这个head是相对的根节点
            while(!stack.isEmpty() || head != null){//栈不为空 或者当前子树不为空        ( 比如左边界最后一个点 子树就为空,但是栈里还有东西,就还会进whil)
                if(head != null){
                    //子树左边界全部进栈
                    stack.push(head);
                    head = head.left;
                }else{
                    //栈弹出一个节点,打印
                    //弹出节点为head,对右子树 左边界进栈
                    head = stack.pop();
                    System.out.print(head.val + " ");
                    head = head.right;
                }
            }
            System.out.println();
        }
    }
    //后序打印所有节点,非递归版
    //这是用两个栈的方法
    /*
    算法:
        先 :中 右 左(出栈才嫩实现正确顺序)
        先`:中 左 右(调换出栈顺序)
        后 :左 右 中(把 先` 出栈顺序反转),那就是 让先`进后栈再出栈
     */
    public static void postOrder(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);
                }
            }
            //此时已全部进collect栈,将其输出
            while(!collect.isEmpty()){//栈嘛,输出就没了,不用++
                System.out.print(collect.pop().val+" ");
            }
        }
        System.out.println();
    }

    //后序打印所有节点,非递归版
    //这是用1个栈的方法
    //先处理左右字数,再返回网上。h是哨兵
    //                       左子树==h说明左边已经处理完,该处理右子树
    //                       右子树==h说明左右子树都处理完,往上走,回到相对的根节点
    public static void postOrder2(TreeNode h) {
        if(h != null){
            Stack<TreeNode> stack = new Stack();
            stack.push(h);
            //如果始终没有打印过节点,h就一直是root头节点
            //一旦打印过节点,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.print(cur.val+" ");
                    h = stack.pop();
                }
            }
            System.out.println();
        }
    }
}

运行结果

相关推荐
karry_k5 小时前
MyBatis批量insert-select踩坑:useGeneratedKeys=true 可能让PostgreSQL返回大量插入结果
java·后端
karry_k5 小时前
PostgreSQL 在 MyBatis 中执行正常 SQL 失效:一次 DELETE USING 踩坑记录
java·后端
vibecoding日记7 小时前
双非如何快速入职字节等大厂大模型?真实案例分析:推理优化和投机解码
算法·求职·大模型工程师
yszaygr21389 小时前
Verilog参数化游程编码RLE模块
算法
SamDeepThinking9 小时前
从源码到代码:MyBatis-Flex 与 MyBatis-Plus 的逐项对比
java·后端·程序员
望易9 小时前
刚设计的大模型架构-双域耦合认知框架
算法·架构
她的男孩12 小时前
Spring Boot 接 Flowable 工作流:用 3 个注解搭一个请假审批流程
java·后端·架构
复杂网络13 小时前
多个 Claude Code 与多个 Codex 协同工作:设计与实现方案
算法
荣码13 小时前
LLM结构化输出:让AI返回JSON而不是废话,我踩了4个坑
java·python