二叉树的后续遍历(迭代法)

迭代法实现二叉树的后续遍历

1、递归版本

public static void dfs(TreeNode root){if(root==null){return;}if(root.left!=null)dfs(root.left);if(root.right!=null)dfs(root.right);System.out.println(root.val);
}

从递归版本可以看出我们第一步需要遍历完所有的左节点
这里我们使用一个栈来存储树的节点,模拟递归的先进后出。

Stack<TreeNode> stack = new Stack<>();
if(root!=null){return;
}
stack.push(root);
while(!stack.isEmpty()){//遍历所有的左节点直到左节点为nullwhile(root!=null&&root.left!=null){root = root.left;stack.push(root);}//再看递归的第二步就是访问右子树。root = stack.pop();  //取出栈顶元素,准备遍历它的右子树if(root.right==null){ //说明没有右子树,就可以直接访问root节点了System.out.println(root.val);}else{//然后就又会回到上面那个while循环遍历这个右子树所有的左节点root = root.right; stack.push(root);}
}

上面就是大致的逻辑,但还有两个重要的问题没有解决。
问题1:关于左子树的重复访问。
1、当栈顶节点为3时,root = stack.pop() 。此时root指向3节点

2、然后进入while循环,又会将6号节点再次访问一遍。因为1号节点已经访问过6了。

红色箭头表示对于root节点,访问它左子树的所有左节点。
绿色箭头表示3节点,访问它左子树的所有左节点。可以看出6节点是重复访问了的。
在这里插入图片描述
解决方法:对于从栈中取出的节点,如果没有右子树就设置为null。

Stack<TreeNode> stack = new Stack<>();
if(root!=null){return;
}
stack.push(root);
while(!stack.isEmpty()){while(root!=null&&root.left!=null){root = root.left;stack.push(root);}root = stack.pop();  if(root.right==null){ root = null;  //防止重复访问左节点System.out.println(root.val);}else{root = root.right; stack.push(root);}
}

问题2:
栈顶取出的节点有右子树的情况下,造成该节点没有被访问。

while(!stack.isEmpty()){while(root!=null&&root.left!=null){root = root.left;stack.push(root);}root = stack.pop();  if(root.right==null){ root = null;System.out.println(root.val);}else{  //含有右子树时。这时的root并没有被访问,而root也被root = root.right;覆盖掉了。所以就会造成当前节点root缺失访问。root = root.right; stack.push(root);}
}

解决方案:在root被root = root.right覆盖之前再将root存回栈中。
我们将root取出来的目的就是访问它的右子树。

while(!stack.isEmpty()){while(root!=null&&root.left!=null){root = root.left;stack.push(root);}root = stack.pop();  if(root.right==null){ root = null;System.out.println(root.val);}else{  stack.push(root); //保存当前节点root = root.right; stack.push(root); //保存当前节点的右子节点}
}

虽然解决了在栈顶取出的节点有右子树的情况下造成该节点没有被访问的问题,但又引出了一个新的问题,重复访问右子节点。

为了解决缺失访问时将2节点存入了栈两次。

1、一次是遍历所有左子树的所有左子节点加入的。(这次的加入目的是用来遍历该节点右子树的)

2、一次是为了解决缺失访问又将2节点存入栈中。(这次的目的是为了在遍历完右子树后再访问2节点用的。因为是后序遍历)
在这里插入图片描述
通过代码可以看出,如果我们不加以限制,那么这个2节点就会第三次,第四次…入z栈造成重复访问。

我们的需求是对于有右子树的节点只访问两次。所以我们可以引入一个标记。
TreeNode pre = null
pre变量的作用就是标识该节点的右子树是否已经遍历过了,如果遍历过了。我们就不将其再次入栈了。
当pre==root.right说明右子树已经访问过了。

最终版本

//这个pre防止重复遍历右子树
TreeNode pre = null;while(!stack.isEmpty()){while (root!=null&&root.left != null) {root = root.left;stack.push(root);}root = stack.pop();//pre==root.rightif(root.right==null||pre==root.right){pre = root;System.out.println(root.val);//这个root设置为null防止重复遍历左子树root = null;}else{stack.push(root);root = root.right;stack.push(root);}}

如果节点2的右子树等于pre就说明这个右子树已经访问过了。2节点的左右子树都访问完就可以按照同样操作继续处理1节点了。
在这里插入图片描述
从图中可以看出pre指针是从下往上一步一步传递上去的。

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

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

相关文章

树莓派基金会近日发布了新版基于 Debian 的树莓派操作系统

树莓派基金会&#xff08;Raspberry Pi Foundation&#xff09;近日发布了新版基于 Debian 的树莓派操作系统&#xff08;Raspberry Pi OS&#xff09;&#xff0c;为树莓派单板电脑带来了新的书虫基础和一些重大变化。 新版 Raspberry Pi OS 的最大变化是它现在基于最新的 Deb…

【表面缺陷检测】钢轨表面缺陷检测数据集介绍(2类,含xml标签文件)

一、介绍 钢轨表面缺陷检测是指通过使用各种技术手段和设备&#xff0c;对钢轨表面进行检查和测量&#xff0c;以确定是否存在裂纹、掉块、剥离、锈蚀等缺陷的过程。这些缺陷可能会对铁路运输的安全和稳定性产生影响&#xff0c;因此及时进行检测和修复非常重要。钢轨表面缺陷…

SpringMVC系列-6 异常处理器

背景 本文作为 SpringMVC系列 的第六篇&#xff0c;介绍SpringMVC的异常处理器。内容包括异常处理器的使用方式、实现原理和内置异常处理器的装配过程。 1.使用方式 自定义异常类&#xff0c;用于异常处理器&#xff1a; public class ClientException extends RuntimeExce…

CTF-php特性绕过

注意&#xff1a;null0 正确 nullflase 错误 Extract变量覆盖 <?php$flagxxx; extract($_GET);if(isset($shiyan)){ $contenttrim(file_get_contents($flag));//trim移除引号if($shiyan$content){ echoctf{xxx}; }else{ echoOh.no;} }?> extract() 函数从数组中将…

主流大语言模型的技术细节

主流大语言模型的技术原理细节从预训练到微调https://mp.weixin.qq.com/s/P1enjLqH-UWNy7uaIviWRA 比较 LLaMA、ChatGLM、Falcon 等大语言模型的细节&#xff1a;tokenizer、位置编码、Layer Normalization、激活函数等。2. 大语言模型的分布式训练技术&#xff1a;数据并行、…

如何配置微信小程序id

使用uni-app开发微信小程序项目&#xff0c;配置好微信小程序id是必不可少的。 一、如何找微信小程序id 二、如何配置微信小程序id

Jupyter Notebook还有魔术命令?太好使了

在Jupyter Notebooks中&#xff0c;Magic commands&#xff08;以下简称魔术命令&#xff09;是一组便捷的功能&#xff0c;旨在解决数据分析中的一些常见问题&#xff0c;可以使用%lsmagic 命令查看所有可用的魔术命令 插播&#xff0c;更多文字总结指南实用工具科技前沿动态…

每日一题 274. H 指数(中等)

先讲一下自己的复杂的写法 第一眼最大最小值问题&#xff0c;直接在0和最大被引次数之间二分找答案先排序&#xff0c;再二分&#xff0c;&#xff0c;&#xff0c; 正解&#xff1a; 排序得到 citations 的递减序列&#xff0c;通过递增下标 i 遍历该序列显然只要排序后的 …

102.linux5.15.198 编译 firefly-rk3399(1)

1. 平台&#xff1a; rk3399 firefly 2g16g 2. 内核&#xff1a;linux5.15.136 &#xff08;从内核镜像网站下载&#xff09; 3. 交叉编译工具 gcc version 7.5.0 (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 4. 宿主机&#xff1a;ubuntu18.04 5. 需要的素材和资料&#xff…

人工智能(AI)在医疗领域的应用

人工智能&#xff08;AI&#xff09;在医疗领域的应用 人工智能&#xff08;AI&#xff09;在医疗领域的应用近年来得到了广泛的关注。其中&#xff0c;AI辅助治疗疾病的技术成为了研究热点。本文将介绍AI辅助治疗疾病的技术&#xff0c;包括其定义、应用场景、案例分析和发展…

Kafka集群

Kafka集群 1、Kafka 概述1.1消息队列背景1.2类型1.3Kafka 定义1.4Kafka 简介 2、消息队列好处3、消息队列的模式4、Kafka 的特性5、Kafka 系统架构4、部署 kafka 集群4.1下载安装包4.2 安装 Kafka4.2.1 修改配置文件4.2.2 修改环境变量4.2.3 配置 zookeeper启动脚本4.2.4 设置…

黑猪肉经营配送商城小程序商城效果怎样

对产品商家来说&#xff0c;如今线下流量匮乏难以增长&#xff0c;线上已经成为商家们重要的经营渠道&#xff0c;但入驻第三方平台也存在诸多痛点&#xff0c;因此更多企业品牌商家选择自建私域卖货平台完善更多生意。 微信作为私域主阵地&#xff0c;自然是企业们不可错过的…

论文-分布式-并发控制-并发控制问题的解决方案

目录 参考文献 问题 解法与证明 易读版本 参考文献 Dijkstra于1965年发表文章Solution of a Problem in Concurrent Programming Control&#xff0c;引出并发系统下的互斥(mutual exclusion)问题&#xff0c;自此开辟了分布式计算领域Dijkstra在文中给出了基于共享存储原子…

Linux——文件权限属性和权限管理

文件权限属性和权限管理 本章思维导图&#xff1a; 注&#xff1a;本章思维导图对应的Xmid文件和.png文件都以传到“资源” 文章目录 文件权限属性和权限管理1. sudo提权和sudoers文件1.1 sudo提权和成为root的区别 2. 权限2.1 Linux群体2.1.1 为什么要有所属组2.1.2 修改文件…

深入理解Linux网络笔记(五):深度理解本机网络IO

本文为《深入理解Linux网络》学习笔记&#xff0c;使用的Linux源码版本是3.10&#xff0c;网卡驱动默认采用的都是Intel的igb网卡驱动 Linux源码在线阅读&#xff1a;https://elixir.bootlin.com/linux/v3.10/source 4、深度理解本机网络IO 1&#xff09;、跨机网络通信过程 …

【笔录】TVP技术沙龙:寻宝AI时代

目录 引言大模型的应用案例大模型三问模型落地可行性考量维度AIGC的几个可行应用方向AIGC的存储LLM工程应用范式演进LLM编程协作范式变化 引言 大模型是10倍的机会&#xff0c;但并不是平均主义的机会&#xff0c;没有低垂的果实。 企业想在大模型的赛道上跑出成绩&#xff0c;…

光谱图像论文浅读

文章目录 Hyperspectral Image Super-Resolution via Deep Spatiospectral Attention Convolutional Neural Networks Hyperspectral Image Super-Resolution via Deep Spatiospectral Attention Convolutional Neural Networks 通过上采样高光谱保留其光谱特征&#xff0c;采用…

vscode连接服务器一直retry

解决方法 打开vscode控制面板&#xff0c;输入命令remote-ssh: kill vs code server on host 选择一直连接不上的服务器端口 重新连接

【鸿蒙软件开发】Stage模型开发概述应用/组件级配置

文章目录 前言一、基本概念1.1 UIAbility 组件1.2 ExtensionAbility 组件1.3 Context1.4 AbilityStage1.5 Stage模型开发流程应用组件开发了解进程模型了解线程模型应用配置文件 二、Stage模型应用/组件级配置2.1 为什么需要这个操作2.2 应用包名配置2.3 应用图标和标签配置2.4…

人工智能在疾病治疗中的应用:机遇与挑战

人工智能在疾病治疗中的应用&#xff1a;机遇与挑战 随着人工智能技术的飞速发展&#xff0c;其在诸多领域的应用价值日益显现。本文将探讨人工智能技术在疾病治疗中的应用&#xff0c;包括其背景意义、技术概述、具体应用、发展前景以及总结。 一、背景意义 随着医学技术的…