【数据结构与算法】二叉树的非递归前中后序遍历

news2024/11/23 19:11:40

🌠作者:@阿亮joy.
🎆专栏:《数据结构与算法要啸着学》
🎇座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根
在这里插入图片描述


目录

    • 👉前言👈
    • 👉二叉树的前序遍历👈
    • 👉二叉树的后序遍历👈
    • 👉二叉树的中序遍历👈
    • 👉总结👈

👉前言👈

二叉树的前中后遍历如果采取递归的方式来实现,是相当容易的事情。递归之所以强大,是因为有系统自动压栈。那么非递归的前中后序遍历就是借助栈,通过我们自己手动压栈来实现二叉树的遍历。当然除了递归和非递归的遍历方式,还有二叉树的 Morris 遍历,这部分内容也将会在下一篇博客中呈现给大家!那话不多说,直接开整!

👉二叉树的前序遍历👈

给你二叉树的根节点 root ,返回它节点值的前序遍历。

在这里插入图片描述

二叉树的非递归前序遍历实现步骤:

  1. 首先申请一个栈,如果头节点不为空,将头节点放入栈中。
  2. 当栈不为空时,while循环继续以下操作:弹出栈顶节点记为cur,然后对cur进行处理(在本道题中,处理cur的操作是将cur->val插入到vector的尾部)。如果节点cur的左右孩子均不为空,先将右孩子压入栈中,再将左孩子压入栈中。注意:如果孩子为空,就不需要压入栈中。
  3. 回到第 2 步,继续进行while循环判断。循环结束后,vector中存储的就是二叉树的前序遍历。

为了验证以上步骤的正确性,我为大家举了一个例子。见下图所示:

在这里插入图片描述

为什么以上过程就能够得到正确的前序遍历呢?因为入栈顺序是头、右、左,那么出栈顺序就是头、左、右(中序遍历的顺序)。注:出栈的顺序并不是左、右、头,因为头节点入栈后就出栈了,而左孩子出栈后,左孩子的左孩子和右孩子也要进栈,那么右孩子就被压在栈底了,并不是马上就能访问到它。

class Solution 
{
public:
    vector<int> preorderTraversal(TreeNode* root) 
    {
        vector<int> ret;
        if(root != nullptr)
        {
            // 头节点不为空,头节点先入栈
            stack<TreeNode*> st;
            st.push(root);
            // 栈不为空,while循环继续
            while(!st.empty())
            {
                // 弹出栈顶节点
                TreeNode* cur = st.top();
                st.pop();
                // 处理cur
                ret.push_back(cur->val);
                // 右孩子先入栈,左孩子后入栈
                if(cur->right != nullptr)
                {
                    st.push(cur->right);
                }
                if(cur->left != nullptr)
                {
                    st.push(cur->left);
                }
            }
        }
        return ret;
    }
};

在这里插入图片描述


👉二叉树的后序遍历👈

给定一个二叉树的根节点 root ,返回 它的后序遍历 。

在这里插入图片描述

二叉树的非递归后序遍历实现步骤:

  1. 首先申请两个栈,一个为辅助栈st1,另一个为收集栈st2。如果头节点不为空,将头节点压入辅助栈st1中。
  2. 当辅助栈st1不为空时,while循环继续以下操作:弹出栈顶节点记为cur,然后将cur压入收集栈st2中。如果节点cur的左右孩子均不为空,先将左孩子压入辅助栈st1中,再将右孩子压入辅助栈st1中。注意:如果孩子为空,就不需要压入栈中。
  3. 回到第 2 步,继续while循环判断。循环结束后,再将收集栈st2中的节点依次弹出就能够得到后序遍历的结果了。

为何以上步骤就能够得到正确的后序遍历结果呢?因为入辅助栈的顺序是头、左、右,那么出辅助栈的顺序是头、右、左(理由同前序遍历)。而出辅助栈的顺序就是入收集栈的顺序,即如收集栈的顺序就是头、右、左,所以出收集栈的顺序就是左、有、头(后序遍历的顺序)。注:收集栈是将全部节点收集完才依次出栈的,并不像辅助栈那样边出栈边入栈。如果还是不了解以上过程的,大家可以按照以上过程画一遍图,那么就会对以上过程会有更深的理解了。

class Solution 
{
public:
    vector<int> postorderTraversal(TreeNode* root) 
    {
        vector<int> ret;
        if(root != nullptr)
        {
            stack<TreeNode*> st1;   // 辅助栈
            stack<TreeNode*> st2;   // 收集栈
            // 头节点先入辅助栈
            st1.push(root);
            while(!st1.empty())
            {
                TreeNode* cur = st1.top();
                st1.pop();
                // cur压入收集栈中
                st2.push(cur);
                // 先将左孩子压入辅助栈,再将右孩子压入辅助栈
                if(cur->left != nullptr)
                {
                    st1.push(cur->left);
                }
                if(cur->right != nullptr)
                {
                    st1.push(cur->right);
                }
            }

            // 收集结果
            while(!st2.empty())
            {
                ret.push_back(st2.top()->val);
                st2.pop();
            }
        }
        return ret;
    }
};

在这里插入图片描述


👉二叉树的中序遍历👈

给定一个二叉树的根节点 root ,返回 它的中序遍历 。

在这里插入图片描述

二叉树的非递归后序遍历实现步骤:

  1. 如果头节点不为空,则申请一个栈和一个指针变量TreeNode* cur并且头节点的左边界上的节点依次进栈。
  2. 当栈不为空或者cur不为空时,while循环继续一下操作:弹出栈顶节点赋值给cur,然后对cur进行处理(在本道题中,处理cur的操作是将cur->val插入到vector的尾部)。如果cur有右子树,则将右子树左边界上的节点依次压入栈中。
  3. 回到第 2 步,继续while循环判断。循环结束后,就能得到中序遍历的结果。

在这里插入图片描述
为什么按照以上步骤就能够得到正确的中序遍历呢?因为每一课二叉树都可以被左边界分解掉。入栈的顺序是头、左,出栈的顺序是左、头,且让左孩子的右子树的左边界入栈。那么出栈的顺序就是左、头、右了,也就是中序遍历的顺序。

class Solution 
{
public:
    vector<int> inorderTraversal(TreeNode* root) 
    {
        vector<int> ret;
        if(root != nullptr)
        {
            stack<TreeNode*> st;
            TreeNode* cur = root;
            while(!st.empty() || cur != nullptr)
            {
                // 左边界入栈
                if(cur != nullptr)
                {
                    st.push(cur);
                    cur = cur->left;
                }
                else    // 到达左边界的空节点了
                {
                    // 弹出栈顶节点
                    cur = st.top();
                    st.pop();
                    ret.push_back(cur->val);
                    // 如果右子树不为空,则下一次循环右子树的左边界会进栈
                    cur = cur->right;   
                }
            }
        }
        return ret;
    }
};

在这里插入图片描述

👉总结👈

本篇博客主要讲解了二叉树的非递归式前中后序遍历。那么以上就是本篇博客的全部内容了,如果大家觉得有收获的话,可以点个三连支持一下!谢谢大家!💖💝❣️

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

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

相关文章

WebSphere8 批量安装和制作介质服务器

WAS 8.5 介质准备 1、安装install manager 2、安装IBM Packaging Utility unzip pu.offering.disk.linux_1.5.3000.20120531_2025.zip cd disk_linux/InstallerImage_linux ./consoleinst.sh 跟着向导安装。 3、安装PU mkdir pu cd pu unzip ../pu_1.5.3.zip ./imcl i…

如何使用集成在 SharePoint 中的开源 ONLYOFFICE 文档替代微软 Office

ONLYOFFICE 文档是一款开源的办公套件&#xff0c;在 GNU AGPL v3.0 下分发。它包括基于网络的查看器和协作编辑器&#xff0c;可用于处理文本文档、电子表格和演示文稿&#xff0c;与 OOXML 格式高度兼容。 ONLYOFFICE 文档可以与多种云服务集成&#xff0c;如 Nextcloud、ow…

仅CPU服务器pytorch ,torch_geometric安装配置

写在开头&#xff0c;做了整整三年的多组学数据分析&#xff0c;各种模式动物、组织、细胞系的各种组学数据&#xff0c;该怎么串联成我的论文&#xff1f;就是我要开启深度学习小白模式了。 万种流程先从环境配置开始&#xff0c;先说说环境&#xff0c;其实当家的有多GPU超大…

儿童护眼灯哪个好?四款儿童护眼台灯测评

儿童护眼灯在孩子的学习过程中起到了很重要的作用&#xff0c;53.7%的青少年们都有近视的现象&#xff0c;而好的台灯不仅照明非常柔和&#xff0c;而且对眼睛没有刺激和伤害&#xff0c;护眼灯相比传统电灯&#xff0c;一是古县更加明亮且可以调节&#xff0c;二是有护眼技术的…

HANA 的 calculation view出现模糊关联 ambiguous join

一旦我们用了join&#xff0c;那就会有个Analytic Engine分析引擎来确保不是唯一连接的时候&#xff0c;关键值不会被重复。 啥是模糊关联&#xff1f; 一般来讲关联基数是1&#xff1a;n, 或者n:1,或者 m:n都是。 以上两个关联&#xff0c;结果集如下&#xff1a; 这时候&a…

php学习笔记-php会话控制,cookie,session的使用,cookie自动登录和session 图书上传信息添加和修改例子-day07

php学习笔记-php会话控制及web常用的预定义变量-day071、$_REQUEST2、$_SERVER3、$_COOKIE3.1 cookie的内容3.2 cookie的分类3.3 php中cookie的使用3.4 cookie自动登录小demo4、$SESSION4.1 session的工作原理4.2 session的使用4.2.1 修改php.ini中的session配置4.2.2 开启sess…

Android 深入系统完全讲解(13)

3 编译过程讲解 1 系统的编译过程 Android 的编译使用的 Makefile&#xff0c;推荐大家使用《GNU make 中文手册》&#xff0c;这本书有电子版&#xff0c;非常方便&#xff0c;主要是要理解清楚 Makefile 的规则&#xff0c;编译策略&#xff0c;可以通过写简单的编译机制&am…

【Java项目推荐】值得写到简历上的项目--黑马点评

优惠卷秒杀前言优惠券秒杀实现优惠券秒杀下单超卖问题一人一单分布式锁redis中加锁的一些特殊情况手动实现分布式锁分布式锁误删情况1分布式锁误删情况2lua脚本解决多条命令的原子性问题Redisson秒杀优化异步秒杀思路基于redis完成秒杀资格判断基于阻塞队列实现异步下单总结Red…

70、SSDNeRF: Semantic Soft Decomposition of Neural Radiance Fields

简介 官网&#xff1a;https://www.siddhantranade.com/research/2022/12/06/SSDNeRF-Semantic-Soft-Decomposition-of-Neural-Radiance-Fields.html SSDNeRF&#xff0c;将语义信号与场景的辐射信号联合编码&#xff0c;提供了场景的软分解为语义部分&#xff0c;能够正确编码…

【HCIA-openEuler】实验手册—09【openEuler综合实践】

文章目录一、实验介绍1、关于本实验2、实验目的二、实验任务配置1、配置思路2、配置步骤步骤1&#xff1a;挂载系统ISO&#xff0c;并配置好本地dnf源步骤2&#xff1a;配置软件安装源步骤3&#xff1a;安装文件共享服务三、设置文件共享用户与权限1、实验介绍&#xff08;1&am…

【Linux】编辑器 - vim 的使用与配置

目录 1、vim的基本概念 2、vim的基本操作 2.1、vim 编辑器的进入与退出 2.2、插入模式 2.3、命令模式 2.4、底行模式 3、vim的配置 3.1、自定义配置 3.2、自动化配置 vim 的前身是 vi&#xff0c;vi/vim的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;…

Java对时间的处理

Date用的最多这里主要介绍该类。java.util 包提供了 Date 类来封装当前的日期和时间。 Date 类提供两个构造函数来实例化 Date 对象。 package com.company; import java.util.Date;public class Main {public static void main(String[] args) {// write your code hereSyste…

阿里云Docker仓库操作

为什么用阿里云docker有自己的仓库服务器&#xff0c;但是对没掏钱的&#xff08;白嫖&#xff09;用户并不是那么友好&#xff0c;有两个很大的限制&#xff1a;免费用户&#xff0c;在6个月之内如果没有任何操作&#xff0c;将会被自动删除&#xff0c;真的很糟糕啊。匿名用户…

港科夜闻|广州市花都区与香港科大(广州)合作建设科研智库,发展AI智慧农业...

关注并星标每周阅读港科夜闻建立新视野 开启新思维1、广州市花都区与香港科大(广州)合作建设科研智库&#xff0c;发展AI智慧农业。1月8日&#xff0c;广州市花都区人民政府和香港科大(广州)在广州举行签约仪式&#xff0c;根据协议&#xff0c;香港科大(广州)和花都区人民政府…

JS案例:接口加解密与防重放

目录 前言 功能设计 客户端的功能点&#xff08;client&#xff09; 服务端的功能点&#xff08;server&#xff09; 功能实现 工具函数 client.js&#xff08;客户端&#xff09; server.js&#xff08;服务端&#xff09; 实现效果 写在最后 前言 在网络通信中&am…

远程会计人员如何通过数字工作流程完成工作

远程会计人员如何通过数字工作流程完成工作 当大多数员工居家办公时&#xff0c;会计部门通常会敏锐地感受到挑战。如果您的组织开始数字化转型或只迈出了第一步&#xff0c;您会发文档管理系统现在已成为必备品&#xff0c;而不是可有可无的。现在是时候实施数字工作流程&…

论文投稿指南——中文核心期刊推荐(地理学)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

Mysql操作指令

Mysql操作指令 创建数据库 下面写具体案列一步步学 这里基本上线在sqlyog里面写sql&#xff0c;因为关于java程序和mysql数据库的连接还没有学 图形化操作数据库之前的可视化有 这里只讲指令凑在哦 注意 默认创建库 用uft8字符集&#xff0c;校对规则的uf8_general_ci不区分大…

< Linux >:环境变量

目录 环境变量 常见的环境变量 基本概念 查看环境变量内容的方法 测试环境变量PATH 与环境变量相关的命令 Linux操作系统下C/C程序代码中获取环境变量的方式 环境变量的组织方式 环境变量通常具有全局属性 环境变量 问题&#xff1a; 注意&#xff1a;可执行程序 等价于 命令/指…

Flutter 开发一个自己的 package(纯Dart)并提交到pub.dev上

小提示第一步&#xff1a;创建一个 package第二步&#xff1a;实现我们的package第三步&#xff1a;发布到 pub.dev 上。END发布的准备工作小提示 Flutter 轮子库。本文是为大家讲述怎么自己写个轮子发布到到上面。 https://pub.flutter-io.cn/packages 第一步&#xff1a;创建…