二叉树的迭代遍历

news2024/12/27 14:02:28

二叉树的迭代遍历

前序遍历

基本思路

基本思路其实很简单, 使用递归遍历的时候, 一直是系统帮我们把其他数据压栈, 举个例子

image-20230105193148870

=> ans = [5,4,6,2,1,null,null]

前序遍历的序列是: [5,4,2,1,6] , 栈的出入顺序是, 先入, 后出, 假如我们想要一个元素先出, 就要让它后入栈

基本思路就是 : 先把 root = 5 入栈 , 然后出栈, 访问 5 , 然后把 5 的 右子树 和 左子树节点(注意是右子树和左子树)分别入栈

此时栈内 : {6, 4} 栈顶是 4, 然后我们再把栈顶元素 4 出栈, 访问 4, 再把 4的右子树和左子树的节点入栈

此时栈内容 : {6, 1, 2} 再把栈顶元素 2出栈, 重复上面的过程,

image-20230105194256873

在这个过程中, 因为我们是先把右子树入栈, 再入栈的左子树, 所以保证了左子树在栈顶, 所以在出栈时, 左子树先出栈, 右子树后出栈

算法流程 :

  1. 将root入栈
  2. 将栈顶元素出栈, node = stack.pop() , 将node.val 存入结果数组, 将node.right和node.left放入栈
  3. 重复上面过程
  4. stack.isEmpty() 算法结束

代码实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {

    private LinkedList<Integer> ans = new LinkedList<>();
    public List<Integer> preorderTraversal(TreeNode root) {

        if(root == null) {
            return ans;
        }

        Stack<TreeNode> stack = new Stack();

        stack.add(root);

        while(!stack.isEmpty()) {
            
            TreeNode node = stack.pop();
            
            // 访问节点
            ans.add(node.val);
            
            // 将其右子树和左子树节点放入
            if(node.right != null) {
                stack.push(node.right);
            }

            if(node.left != null){
                stack.push(node.left);
            }
        }
        return ans;
    }
}

中序遍历

基本思路

image-20230105205027183

使用一个指针 p 一直向左走, 将走过的节点放入栈中, 这里注意, 栈是先入后出的, 所以出栈时的顺序正好是我们中序遍历的顺序, 当指针走到叶子节点时,

继续向左走就会指向null, 如上图 :

此时栈中 {5,4,2} , p 此时指向 2 的左子树, 但是左子树是null, 我们就需要将栈顶元素出栈 2 , 此时指针再指向 2 的右子树, 以此类推,

继续向左走,

算法流程 :

  1. p 指向 root
  2. p != null p 一直向左边移动 : p = p.left
  3. p == null , node = stack.pop() 出栈, 将栈顶元素放入结果集, p = node.right;
  4. p == null || stack.isEmpty , 算法结束

代码实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {

    private List<Integer> ans = new ArrayList<>();
    public List<Integer> inorderTraversal(TreeNode root) {

        if(root == null) {
            return ans;
        }

        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;

        while(cur != null || !stack.isEmpty()) {
            
            // 让指针一直向左走
            if(cur != null) {
                stack.push(cur);
                cur = cur.left;
            }else{
                // 为空, 说明走到最左边了
                // 元素出栈
                // cur 之前一直是指向左边, 此时为null, 说明左边没有
                // 取出根节点
                cur = stack.pop();
                ans.add(cur.val);
                // 向右移动
                cur = cur.right;
            }
        }

        return ans;
    }
}

后续遍历

和前序遍历思路一样, 但是需要简单调整下, 前序遍历是 中左右, 后序是左右中, 我们只需要让前序遍历添加左右子树时先添加 左子树, 后添加右子树

得到 中右左的顺序, 然后再逆序即可.

代码实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    
    private List<Integer> ans = new ArrayList<Integer>();
    public List<Integer> postorderTraversal(TreeNode root) {

        if(root == null) {
            return ans;
        }

        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);

        while(!stack.isEmpty()) {

            // 出栈
            TreeNode node = stack.pop();
            ans.add(node.val);

            // 前序是 中左右, 后续是 左右中
            // 前序逆序后 右左中, 我们只要在添加的时候
            // 让顺序是 中右左, 这样逆序后就是 左右中, 就是后序的顺序了
            if(node.left != null) {
                stack.push(node.left);
            }

            // 将左子树和右子树入栈
            if(node.right != null) {
                stack.push(node.right);
            }
            
        }

        // 反转结果
        Collections.reverse(ans);
        return ans;
    }
}

层序遍历

基本思路

层序的遍历思路很简单, 借助队列先入先出的思想, 我们只需要不断的把根节点存入, 然后按照队列顺序取出, 取出时再把它们的子树节点存入, 以此类推

关键点是 :

 while(!queue.isEmpty()) {

            int size = queue.size();
            LinkedList<Integer> tmp = new LinkedList<>();

            for(int i = 0 ; i < size ; i++) {
                TreeNode node = queue.remove();
                tmp.add(node.val);

                if(node.left != null) {
                    queue.add(node.left);
                }
                if(node.right != null) {
                    queue.add(node.right);
                }
            }

            ans.add(tmp);
        }

在循环内部, 我们先获取 当前队列的size, 然后再用for循环, 去将当前队列中当前层的元素取出

代码实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    List<List<Integer>> ans = new LinkedList<>();
    public List<List<Integer>> levelOrder(TreeNode root) {
        
        if(root == null) {
            return ans;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);

        while(!queue.isEmpty()) {

            int size = queue.size();
            LinkedList<Integer> tmp = new LinkedList<>();

            for(int i = 0 ; i < size ; i++) {
                TreeNode node = queue.remove();
                tmp.add(node.val);

                if(node.left != null) {
                    queue.add(node.left);
                }
                if(node.right != null) {
                    queue.add(node.right);
                }
            }

            ans.add(tmp);
        }

        return ans;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/175101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STC12驱动MLX90614红外测温模块在LCD1602显示

文章目录1、基本简介2、通信方式3、参考STC12例程参考文献1、基本简介 2、通信方式 通过芯片手册我们可以了解到这个模块的输出有PWM和SMBus方式&#xff0c;PWM长期做嵌入式开发的已经很熟悉了&#xff0c;那么什么是SMBus呢&#xff1f; SMBus&#xff08;系统管理总线&…

swift(3)

目录 while循环&#xff0c;repeat while循环 String基本操作 Array数组 Set集合 while循环&#xff0c;repeat while循环 import UIKitvar a0 while(a<5){print(a) }简单的while循环&#xff0c;我这一个循环下去&#xff0c;我playground直接被强制退出。 import UIK…

go的基本数据类型转换

目录 1.(整形转化)基本语法 2.小知识 3.基本数据类型和string的转换 A.fmt.Sprintf("%参数", 表达式) B. 使用 strconv 包的函数 4.string和基本数据类型转换 Go在不同类型的变量之间赋值时需要显示转换&#xff0c;不能自动转换 1.(整形转化)基本语法 A.不考…

Elasticsearch7.8.0版本高级查询—— 模糊查询文档

目录一、初始化文档数据二、模糊查询文档2.1、概述2.2、示例12.3、示例2一、初始化文档数据 在 Postman 中&#xff0c;向 ES 服务器发 POST 请求 &#xff1a;http://localhost:9200/user/_doc/1&#xff0c;请求体内容为&#xff1a; { "name":"zhangsan"…

LeetCode 1824. 最少侧跳次数

【LetMeFly】1824.最少侧跳次数 力扣题目链接&#xff1a;https://leetcode.cn/problems/minimum-sideway-jumps/ 给你一个长度为 n 的 3 跑道道路 &#xff0c;它总共包含 n 1 个 点 &#xff0c;编号为 0 到 n 。一只青蛙从 0 号点第二条跑道 出发 &#xff0c;它想要跳到…

SpringCloud(16):Zuul网关服务整合Swagger接口文档

手写Api文档的几个痛点 文档需要更新的时候&#xff0c;需要再次发送一份给前端&#xff0c;也就是文档更新交流不及时。接口返回结果不明确不能直接在线测试接口&#xff0c;通常需要使用工具&#xff0c;比如postman接口文档太多&#xff0c;不好管理1 springcloud快速集成 …

LINUX---进程间通信(IPC)

目录进程间通信&#xff08;IPC&#xff09;介绍&#xff1a;一、管道1、特点&#xff1a;2、原型&#xff1a;父子进程中的管道应用&#xff1a;FIFO1、特点2、原型三、消息队列ftok移除消息队列四.共享内存信号信号携带消息信号量微信QQ聊天就是进程间通信&#xff08;基于网…

大数据技术之Hadoop(MapReduce)

第1章 MapReduce概述 1.1 MapReduce定义 MapReduce是一个分布式运算程序的编程框架&#xff0c;是用户开发“基于Hadoop的数据分析应用”的核心框架。 MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序&#xff0c;并发运行在一个H…

StructuredStreaming Sink

StructuredStreaming Sink Output Modes append 默认追加模式, 将新的数据输出&#xff0c;只支持简单查询 complete 完整模式&#xff0c;支持聚合和排序 update 更新模式&#xff0c;支持聚合不支持排序&#xff0c;没有聚合和append一样 下面这段操作&#xff0c;有聚合…

Python机器学习数据建模与分析——Numpy和Pandas综合应用案例:空气质量监测数据的预处理和基本分析

本篇文章主要以北京市空气质量监测数据为例子&#xff0c;聚集数据建模中的数据预处理和基本分析环节&#xff0c;说明Numpy和Pandas的数据读取、数据分组、数据重编码、分类汇总等数据加工处理功能。同时在实现案例的过程中对用到的Numpy和Pandas相关函数进行讲解。 文章目录数…

新的一年即将到来,分享2023年火爆的行业和值得做的副业兼职项目

明天就是除夕啦&#xff0c;小编还在努力工作着&#xff0c;分享完这一篇文章后&#xff0c;小编也要和家人朋友们一起好好休息下&#xff0c;过一个乐此不疲的春节。今天分享的主要是对明年行业的憧憬以及一些值得做的副业兼职项目&#xff0c;文章比较长&#xff0c;如果觉得…

Spring源码学习:setter循环依赖

1.案例&#xff1a;Component public class A {private B b;Autowiredpublic void setB(B b) {this.b b;}public B getB() {return b;}public void f(){System.out.println(b);} }Component public class B {private A a;Autowiredpublic void setA(A a) {this.a a;}public v…

Ubuntu 终端美化(oh-my-zsh)

文章目录Ubuntu 终端美化&#xff08;oh-my-zsh&#xff09;一、 环境准备二、 配置文件1、 主题2、 修改插件2.1 官方插件2.2 第三方插件Ubuntu 终端美化&#xff08;oh-my-zsh&#xff09; 一、 环境准备 这个美化教程适合于大多数的 Linux 系统&#xff0c;其实可以通用的。…

递归和分治(基础)

目录 一、递归的定义 1、什么时候会用到递归的方法 1. 定义是递归的 2. 数据结构是递归的 3. 问题的解法是递归的 2、应用递归的原则 3、递归调用顺序问题 1. 首先递归的过程可以总结为以下几点&#xff1a; 2. 递归工作栈 二、 递归和非递归的转化 1. 单向递归可…

【JavaGuide面试总结】计算机网络·下

【JavaGuide面试总结】计算机网络下1.HTTP 和 HTTPS 有什么区别&#xff1f;2.HTTP 1.0 和 HTTP 1.1 有什么区别&#xff1f;连接方式状态响应码缓存处理Host头处理带宽优化3.HTTP 是不保存状态的协议, 如何保存用户状态?4.简单说说 ARP 协议的工作原理同一局域网内的 MAC 寻址…

【Java寒假打卡】JavaWeb-ServletContext

【Java寒假打卡】JavaWeb-ServletContext概述域对象ServletContext的配置方式ServletContext的常用方法ServletContext共享数据的方法概述 ServletContext是应用上下文对象&#xff08;应用域对象&#xff09;。每一个应用中只有一个ServletContext对象作用&#xff1a;可以配…

kubernetes集群搭建问题记录

centos7 系统 内核需要升级 centos7内核升级文章 init-config.yaml文件初始化master的时候 advertiseAddress 是主机的ip地址 kubeadm kubelet kubectl 安装 1.19.0 版本&#xff0c;版本高了有问题 yum install -y kubeadm-1.19.0 kubelet-1.19.0 kubectl-1.19.0 master 和…

<Python的字典>——《Python》

目录 1. 字典 1.1 字典是什么 1.2 创建字典 1.3 查找 key 1.4 新增/修改元素 1.5 删除元素 1.6 遍历字典元素 1.7 取出所有 key 和 value 1.8 合法的 key 类型 1. 字典 1.1 字典是什么 字典是一种存储 键值对 的结构. 键值对是计算机/生活中一个非常广泛使用的概念…

【C++算法图解专栏】一篇文章带你掌握前缀和算法(一维+二维)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为 0 基础刚入门数据结构与算法的小伙伴提供详细的讲解&#xff0c;也欢迎大佬们一起交流~ &#x1f4da;专栏地址&#xff1a;https://blog.csdn.net/Newin…

Leetcode.1824 最少侧跳次数

题目链接 Leetcode.1824 最少侧跳次数 题目描述 给你一个长度为 n的 3 跑道道路 &#xff0c;它总共包含 n 1个 点 &#xff0c;编号为 0 到 n 。一只青蛙从 0 号点第二条跑道 出发 &#xff0c;它想要跳到点 n处。然而道路上可能有一些障碍。 给你一个长度为 n 1的数组 ob…