算法通关: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();
        }
    }
}

运行结果

相关推荐
To_OC4 小时前
LC 51 N 皇后:我以为难的是回溯,结果栽在了对角线下标
javascript·算法·leetcode
Scott9999HH4 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔4 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
2401_841495644 小时前
【操作系统】进程同步与互斥实验报告
c++·算法·操作系统·进程·并发·同步·互斥
码智社5 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海5 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖6 小时前
JDK 26 新特性详解
java·开发语言
马优晨6 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区8 小时前
怎么把C语言学到精通?
c语言·开发语言