【二叉树进阶】二叉树的前中后序遍历(非递归迭代实现)

文章目录

  • 1. 二叉树的前序遍历
    • 1.1 思路分析
    • 1.2 AC代码
  • 2. 二叉树的中序遍历
    • 2.1 思路分析
    • 2.2 AC代码
  • 3. 二叉树的后序遍历
    • 3.1 思路1
    • 3.2 思路1AC
    • 3.3 思路2
    • 3.4 思路2AC

1. 二叉树的前序遍历

题目链接: link

在这里插入图片描述

不用递归,用迭代算法如何实现对二叉树的前序遍历?
在这里插入图片描述
最终放到一个vector里面返回。

1.1 思路分析

前序遍历的非递归呢我们可以这样来搞:

题目中给的二叉树比较简单,下面通过这样一棵二叉树给大家讲解:
在这里插入图片描述
对它进行非递归的前序遍历,它是这样搞的:
前序遍历是根、左子树、右子树
所以首先从根结点开始,顺着访问左子树:8、3、1
然后现在还有谁没访问?
🆗,是1的左子树、3的左子树,和8的左子树。
所以下面倒着访问1、3、8的左子树就行了。
所以非递归的前序遍历是这样处理的:
他把一棵二叉树分为两个部分

  1. 左路结点
  2. 左路结点的右子树

在这里插入图片描述
对于每一棵左子树,也是同样划分为这两个部分进行处理。

那现在问题来了,如何倒着去处理左路结点的右子树?

那此时我们就可以借助一个栈来搞。
在这里插入图片描述
还是以这棵树为例,从根结点8开始,依次访问左路结点8,3,1。
在访问过程中除了将他们放到要返回的vector里面,再把左路结点放到栈里面

在这里插入图片描述
然后:
依次取栈顶元素(1 3 8 ),访问它们的右子树。
那这是不是就是一个前序遍历的顺序啊。
那如何处理它们的右子树啊?
🆗,这是不是一个子问题啊。
首先1出栈,访问1的右子树,那为空,就直接结束。
在这里插入图片描述
然后再取栈顶元素3,访问它的右子树。
所以我们此时就要循环上去,从3的右子树的根结点6开始,进行同样的处理。
首先访问3的右子树的左路结点并入栈

在这里插入图片描述
然后4、6出栈,先后处理4、6的右子树,对于子树同样循环上去进行处理。
后续也是如此,我这里就不继续往下画了。
大家如果还不是特别理解可以继续往下画完。

1.2 AC代码

那我们来写一下代码:

在这里插入图片描述
在这里插入图片描述

class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {vector<int> ret;stack<TreeNode*> st;TreeNode* cur=root;//循环结束条件://1.cur不为空表示还有树没有访问//2.栈不为空表示还有结点的右子树没处理while(cur||!st.empty()){//遍历左路结点并入栈while(cur){ret.push_back(cur->val);st.push(cur);cur=cur->left;}//取栈顶元素并访问它的右子树TreeNode* top=st.top();st.pop();//怎么处理它的右子树?//子问题,把cur置成右子树的根,上去重新进行循环即可cur=top->right;}return ret;}
};

当然不止我们这里讲的这一种方法,不过我们这个后面比较方便往中序和后序的方向上修改。

2. 二叉树的中序遍历

题目链接: link

接下来我们就来看一下二叉树中序遍历的非递归如何实现
在这里插入图片描述

2.1 思路分析

其实大体的思路还是跟上一道题的差不多,最后写出来跟上一题的代码也基本一样,其中一句代码换一下位置就行了

那我们这里还是,每一棵树都把它分成左路结点和右子树
在这里插入图片描述
回忆一下上一题我们的前序是怎么走的:、
在这里插入图片描述
我们是在左路结点入栈的时候就把它放到要返回的vector里面,因为这就符合前序遍历的顺序。
那现在是中序遍历,中序是先访问左子树,然后再访问根
所以我们先把左路结点入栈,但是不放进vector里面。
在这里插入图片描述
一直走到1的左子树为空然后停止入栈,那这时就可以认为1的左子树是空已经遍历过了。
然后出栈里面的元素(从栈里面取出一个左路结点的时候,就意味着它的左子树已经访问过了),第一个出的是1,那此时遇到1我们要把它放到vector里面吗?
🆗,这时就要放了,因为1的左子树访问过后,就要访问根了(左子树、根、右子树)
在这里插入图片描述
那1的根访问完,然后要访问柚子是,这里1的右是空,但是其它测试用例不一定是空啊。
那要访问右子树怎么办?
是不是还是让它循环上去,从当前左路结点的右子树的根开始进行同样的处理。
当然这里1的右是空,所以下面就直接取栈顶下一个元素了,那就是3
在这里插入图片描述
然后处理3的右子树。
循环上去,从根结点6开始进行同样的处理
左路结点6,4入栈
在这里插入图片描述
然后4出栈,处理4的左,左为空。
接着6出栈,处理6的左
在这里插入图片描述
那对于6的左,就是循环上去,对7这棵子树进同样的处理
7入栈,左为空,不再继续入了。
接着7出栈,放进vector。
在这里插入图片描述
接着处理7的左。
后续也是一样,8出栈,然后处理8的左
大家看现在的访问顺序是不是中序的
在这里插入图片描述
后面我就不画了。

2.2 AC代码

那代码很简单,跟上一题相比,是不是就是入vector的时机变了啊

前序是入栈的时候就放到vector里面,中序是出栈的时候在放到vector里面
在这里插入图片描述
在这里插入图片描述

class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {vector<int> ret;stack<TreeNode*> st;TreeNode* cur=root;while(cur||!st.empty()){//遍历左路结点并入栈while(cur){st.push(cur);cur=cur->left;}//取栈顶元素的时候再入vectorTreeNode* top=st.top();st.pop();ret.push_back(top->val);//处理右子树//子问题,把cur置成右子树的根,上去重新进行循环即可cur=top->right;}return ret;}
};

3. 二叉树的后序遍历

题目链接: link
在这里插入图片描述
那后序遍历的非递归又如何实现呢?
这里提供两种思路

3.1 思路1

思路1呢是这样的:

大家想前序是根、左子树、右子树。
后序是左子树、右子树、根。
那如果我们实现一个根、右子树、左子树的遍历,然后把得到的vector逆置一下是不是就是后序遍历的结果啊。
那怎么能够得到一个根、右子树、左子树的遍历呢?
🆗,我们把前序遍历的代码修改一下,访问完根之后先访问右子树、在访问左子树不就行了嘛。
在这里插入图片描述

3.2 思路1AC

很简单,修改两句代码的事:

在这里插入图片描述
在这里插入图片描述

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {vector<int> ret;stack<TreeNode*> st;TreeNode* cur=root;//循环结束条件://1.cur不为空表示还有树没有访问//2.栈不为空表示还有结点的左子树没处理while(cur||!st.empty()){//遍历右路结点并入栈同时入vectorwhile(cur){ret.push_back(cur->val);st.push(cur);cur=cur->right;}//取栈顶元素并访问它的左子树TreeNode* top=st.top();st.pop();//怎么处理它的左子树?//子问题,把cur置成左子树的根,上去重新进行循环即可cur=top->left;}reverse(ret.begin(),ret.end());return ret;}
};

3.3 思路2

那如果我们就想像上面的前序中序那样按照正确的顺序去实现遍历呢?而不是用刚才这种取巧的方法:

后序遍历是左子树、右子树、根;
而中序遍历是左子树、根、右子树
所以,后序遍历前面的操作和中序是一样的:
还是先让左路结点入栈在这里插入图片描述
然后对于栈顶的元素我们可以直接让它入vector然后pop掉嘛。
中序我们就是这样做的,因为从栈里面取出一个左路结点的时候,就意味着它的左子树已经访问过了,然后中序的话该访问根了,而把栈顶元素放到vector里面然后pop掉就相当于访问根结点。
但是我们后序就不能直接这样了,因为后序要在右子树访问完之后再去访问根

那怎么办?

其实很简单,加一个判断就行了。
能不能直接pop,然后放到vector里面,其实要看情况:
在这里插入图片描述
大家看对于1这种情况我们可不可以直接访问,是不是可以啊,因为1的右子树为空。
那如果是6这种情况呢?
就不可以了,因为它的右子树不为空,所以要先访问右子树7。
那7访问完把7pop掉之后回到6这里,这次可以访问6了吗?
那这时就可以了,因为6的右子树访问过了。
所以两种情况我们可以直接访问根:

  1. 右子树为空
    如果右子树不为空,就不能值访问根,要先访问右子树
  2. 右子树已经访问过了

那右子树为空,这很好判断,但是如何判断一个结点的右子树是否已经访问过了呢?
🆗,我们可以定义一个prev指针,每次处理完一个结点pop掉之后,把这个结点赋值给prev。
然后我们就可以通过prev判断某个结点前面被访问的结点是不是它的右子树
prev==top.right

那思路呢就是这样的,我们来写一下代码:

3.4 思路2AC

在这里插入图片描述
在这里插入图片描述

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {vector<int> ret;stack<TreeNode*> st;TreeNode* cur=root;TreeNode* prev=nullptr;while(cur||!st.empty()){//遍历左路结点并入栈while(cur){st.push(cur);cur=cur->left;}//取到栈顶结点的时候它的左子树已经访问过了TreeNode* top=st.top();//如果当前取到的栈顶结点的右子树为空或者右子树已经被访问过了,就可以访问根结点if(top->right==nullptr||prev==top->right){st.pop();ret.push_back(top->val);//记录prevprev=top;}//否则,就需要先处理右子树else{cur=top->right;}}return ret;}
};

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牛客网Verilog刷题——VL48

牛客网Verilog刷题——VL48 题目答案 题目 在data_en为高期间&#xff0c;data_in将保持不变&#xff0c;data_en为高至少保持3个B时钟周期。表明&#xff0c;当data_en为高时&#xff0c;可将数据进行同步。本题中data_in端数据变化频率很低&#xff0c;相邻两个数据间的变化&…

大模型开发(十五):从0到1构建一个高度自动化的AI项目开发流程(上)

全文共5600余字&#xff0c;预计阅读时间约13~20分钟 | 满满干货(附全部代码)&#xff0c;建议收藏&#xff01; 本文目标&#xff1a;提出一种利用大语言模型(LLMs)加快项目的开发效率的解决思路&#xff0c;本文作为第一部分&#xff0c;主要集中在如何完整的执行引导Chat模…

网盘共享文件的优势及对团队办公的帮助

伴随着科技的发展&#xff0c;互联网逐步渗透了企业办公方式。各种类型的网盘应运而生&#xff0c;成为当下文件共享的主要方式之一。那么网盘共享文件有什么优势&#xff1f;对团队办公有何帮助呢&#xff1f; 网盘共享文件的优势 1、方便快捷&#xff1a;用户通过移动设备即…

git面试题

文章目录 git经常用哪些指令git出现代码冲突怎么解决你们团队是怎么管理git分支的如何实现Git的免密操作 git经常用哪些指令 产生代码库 新建一个git代码库 git init下载远程项目和它的整个代码历史 git clone 远程仓库地址配置 显示配置 git config --list [--global]编辑配置…

Kubernetes 使用 helm 部署 NFS Provisioner

文章目录 1. 介绍2. 预备条件3. 部署 nfs4. 部署 NFS subdir external provisioner4.1 集群配置 containerd 代理4.2 配置代理堡垒机通过 kubeconfig 部署 部署 MinIO添加仓库修改可配置项 访问nodepotingress 1. 介绍 NFS subdir external provisioner 使用现有且已配置的NFS…

设计模式再探——代理模式

目录 一、背景介绍二、思路&方案三、过程1.代理模式简介2.代理模式的类图3.代理模式代码4.代理模式还可以优化的地方5.代理模式的项目实战&#xff0c;优化后(只加了泛型方式&#xff0c;使用CGLIB的代理) 四、总结五、升华 一、背景介绍 最近在做产品过程中对于日志的统一…

2023年自然语言处理与信息检索国际会议(ECNLPIR 2023) | EI Compendex, Scopus双检索

会议简介 Brief Introduction 2023年自然语言处理与信息检索国际会议(ECNLPIR 2023) 会议时间&#xff1a;2023年9月22日-24日 召开地点&#xff1a;中国杭州 大会官网&#xff1a;ECNLPIR 2023-2023 Eurasian Conference on Natural Language Processing and Information Retr…

【机器学习】Cost Function for Logistic Regression

Cost Function for Logistic Regression 1. 平方差能否用于逻辑回归&#xff1f;2. 逻辑损失函数loss3. 损失函数cost附录 导入所需的库 import numpy as np %matplotlib widget import matplotlib.pyplot as plt from plt_logistic_loss import plt_logistic_cost, plt_two_…

自己实现MyBatis 底层机制--抽丝剥茧(上)

&#x1f600;前言 本篇博文是学习过程中的笔记和对于MyBatis底层机制的分析思路&#xff0c;希望能够给您带来帮助&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到…

誉天程序员-瀑布模型-敏捷开发模型-DevOps模型比较

文章目录 2. 项目开发-开发方式2.1. 瀑布开发模型2.2. 敏捷开发模型2.3. DevOps开发模型2.4. 区别 自增主键策略1、数据库支持主键自增自增和uuid方案优缺点 2. 项目开发-开发方式 由传统的瀑布开发模型、敏捷开发模型&#xff0c;一跃升级到DevOps开发运维一体化开发模型。 …

IPv6 over IPv4隧道配置举例

配置IPv6 over IPv4手动隧道示例 组网需求 如图1所示&#xff0c;两台IPv6主机分别通过SwitchA和SwitchC与IPv4骨干网络连接&#xff0c;客户希望两台IPv6主机能通过IPv4骨干网互通。 图1 配置IPv6 over IPv4手动隧道组网图 配置思路 配置IPv6 over IPv4手动隧道的思路如下&…

【雕爷学编程】MicroPython动手做(10)——零基础学MaixPy之神经网络KPU2

KPU的基础架构 让我们回顾下经典神经网络的基础运算操作&#xff1a; 卷积&#xff08;Convolution&#xff09;:1x1卷积&#xff0c;3x3卷积&#xff0c;5x5及更高的卷积 批归一化&#xff08;Batch Normalization&#xff09; 激活&#xff08;Activate&#xff09; 池化&…

单例模式(Singleton)

单例模式保证一个类仅有一个实例&#xff0c;并提供一个全局访问点来访问它&#xff0c;这个类称为单例类。可见&#xff0c;在实现单例模式时&#xff0c;除了保证一个类只能创建一个实例外&#xff0c;还需提供一个全局访问点。 Singleton is a creational design pattern t…

JavaScript场景应用:Canvas实战开发一个二维折线图插件

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f3c6;本文已…

VB6中FSO具体应用详解

文前申明:原文为通用版实例代码,本菜鸟在每例之后加入一个简单的实例(均验证通过),供有需要的朋友参考. 您正在看的VB教程是:VB入门基础认识VB的文件系统对象FSO。 在 VB 编程中经常需要和文件系统打交道&#xff0c;比如获取硬盘的剩余空间、判断文件夹或文件是否存在等。在…

认识主被动无人机遥感数据、预处理无人机遥感数据、定量估算农林植被关键性状、期刊论文插图精细制作与Appdesigner应用开发

目录 第一章、认识主被动无人机遥感数据 第二章、预处理无人机遥感数据 第三章、定量估算农林植被关键性状 第四章、期刊论文插图精细制作与Appdesigner应用开发 更多推荐 遥感技术作为一种空间大数据手段&#xff0c;能够从多时、多维、多地等角度&#xff0c;获取大量的…

PHP语言基础知识(超详细)

文章目录 前言第一章 PHP语言学习介绍 1.1 PHP部署安装环境1.2 PHP代码工具选择 第二章 PHP代码基本语法 2.1 PHP函数知识介绍2.2 PHP常量变量介绍 2.2.1 PHP变量知识&#xff1a;2.2.2 PHP常量知识&#xff1a; 2.3 PHP注释信息介绍2.4 PHP数据类型介绍 2.4.1 整形数据类型2.4…

基于量子同态的安全多方量子求和加密

摘要安全多方计算在经典密码学中一直扮演着重要的角色。量子同态加密(QHE)可以在不解密的情况下对加密数据进行计算。目前&#xff0c;大多数协议使用半诚实的第三方(TP)来保护参与者的秘密。我们使用量子同态加密方案代替TP来保护各方的隐私。在量子同态加密的基础上&#xff…

2023年自动化测试已成为标配?一篇彻底打通自动化测试...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 首先我们从招聘岗…

《面试1v1》ElasticSearch 和 Lucene

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…