94. 二叉树的中序遍历(Swift实现, 迭代)

题目描述

在这里插入图片描述

使用迭代方法解题

class TreeNode {var val: Intvar left: TreeNode?var right: TreeNode?init(_ val: Int) {self.val = valself.left = nilself.right = nil}
}func inorderTraversal(_ root: TreeNode?) -> [Int] {var result = [Int]()    // 用于存储中序遍历的结果var stack = [TreeNode]() // 用于模拟递归的栈var current = root       // 从根节点开始// 当当前节点不为空或栈不为空时继续循环while current != nil || !stack.isEmpty {// 不断将当前节点的左子节点压入栈中,直到当前节点为空while let node = current {stack.append(node)current = node.left}// 弹出栈顶节点,并将其值添加到结果数组current = stack.removeLast()result.append(current.val)// 将当前节点指向弹出节点的右子节点current = current.right}return result
}// 示例用法:
// 构建一个示例二叉树
//      1
//     / \
//    2   3
//   / \
//  4   5let root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left?.left = TreeNode(4)
root.left?.right = TreeNode(5)// 调用中序遍历函数
let result = inorderTraversal(root)
print(result)  // 输出: [4, 2, 5, 1, 3]

分析

理解迭代方式的二叉树中序遍历确实需要一些时间,因为它涉及到手动管理一个栈来模拟递归过程。

手动管理一个栈来模拟递归过程,主要在于理解递归调用的本质:保存当前的执行状态,然后在处理完子任务后恢复这个状态。以下是一些窍门和技巧,帮助你更好地理解和实现这种方式:

理解递归和迭代的等效性

  1. 递归调用栈

    • 每次递归调用,系统会把当前函数的状态(变量、执行位置等)压入系统栈。
    • 当子任务完成后,系统会从栈中恢复上一次的状态继续执行。
  2. 迭代模拟递归

    • 我们需要手动管理一个栈,把当前节点和相关信息压入栈中。
    • 在处理子任务时,可以从栈中恢复之前的状态。

栈操作的核心逻辑

中序遍历的递归方式:

func inorderTraversal(_ root: TreeNode?) -> [Int] {guard let root = root else { return [] }return inorderTraversal(root.left) + [root.val] + inorderTraversal(root.right)
}

转换为迭代方式:

步骤详细解析

  1. 初始化

    • 使用一个栈来存储节点。
    • 使用一个变量 current 来追踪当前节点。
  2. 模拟递归的左子树处理

    • 不断将当前节点压入栈,并移向左子节点,直到当前节点为空。
    • 这一步类似递归调用到最左子节点的过程。
  3. 处理节点并移向右子树

    • 弹出栈顶节点,处理该节点(例如添加到结果数组中)。
    • current 指向该节点的右子节点。

具体代码

class TreeNode {var val: Intvar left: TreeNode?var right: TreeNode?init(_ val: Int) {self.val = valself.left = nilself.right = nil}
}func inorderTraversal(_ root: TreeNode?) -> [Int] {var result = [Int]()        // 存储中序遍历结果var stack = [TreeNode]()    // 栈用于模拟递归var current = root          // 从根节点开始遍历// 当栈不为空或当前节点不为空时循环继续while current != nil || !stack.isEmpty {// 一直向左走,直到没有左子节点while let node = current {stack.append(node)  // 将当前节点压入栈current = node.left // 移动到左子节点}// 弹出栈顶节点并处理current = stack.removeLast() // 弹出栈顶result.append(current.val)   // 处理当前节点// 转向右子树current = current.right      // 移动到右子节点}return result
}// 示例用法:
// 构建一个示例二叉树
//      1
//     / \
//    2   3
//   / \
//  4   5let root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left?.left = TreeNode(4)
root.left?.right = TreeNode(5)// 调用中序遍历函数
let result = inorderTraversal(root)
print(result)  // 输出: [4, 2, 5, 1, 3]

关键点总结

  1. 模拟递归压栈

    • 每次将当前节点压入栈中,然后移动到左子节点。
    • 这相当于递归调用处理左子树。
  2. 模拟递归出栈

    • 当无法继续向左走时,弹出栈顶节点。
    • 处理该节点后,转向右子树。
  3. 继续遍历

    • current 指向右子节点,继续上述过程。

理解示例

对于二叉树:

     1/ \2   3/ \4   5
  • 初始状态
    • current 指向 1,stack 为空。
  • 第一次内循环(处理左子树):
    • 压入 1 -> 压入 2 -> 压入 4 -> 到达 nil
  • 第一次弹出
    • 弹出 4,添加到结果:result = [4]current 指向 nil
  • 第二次弹出
    • 弹出 2,添加到结果:result = [4, 2]current 指向 5。
  • 处理 5
    • 压入 5 -> 到达 nil -> 弹出 5,添加到结果:result = [4, 2, 5]
  • 处理 1
    • 弹出 1,添加到结果:result = [4, 2, 5, 1]current 指向 3。
  • 处理 3
    • 压入 3 -> 到达 nil -> 弹出 3,添加到结果:result = [4, 2, 5, 1, 3]

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

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

相关文章

kali中安装zsteg教程

1、下载文件 git clone http://www.github.com/zed-0xff/zsteg 2、第一步需要保证虚拟机是有网络的,不然无法克隆 3、可以将网络设置成如下后重启,访问百度看看能不能访问,若可以访问,则进行下一步 4、查看源,删除源&…

Python-程序流程控制

目录 1. 分支语句 1.1 if 1.2 if-else 1.3 if-elif-else 2. 循环语句 2.1 while 2.2 for 3.跳转语句 3.1 break 3.2 continue 1. 分支语句 1.1 if aint(input("请输入成绩")) if a>100:print ("牛逼") if a<60:print("不牛逼")1.2 if-e…

期末复习5---PTA

以下是提交正确的代码&#xff1a; int max_len( char *s[], int n ) {int i;int max0;for(i1;i<n;i){if(strlen(s[i])>strlen(s[max]))maxi;}return strlen(s[max]); } 以下是我自己写的代码&#xff1a; 出现的问题是 &#xff1a;括号加的不对&#xff0c;需要细心…

同城如何异地共享文件?

在现代社会中&#xff0c;跨地区的合作变得越来越普遍&#xff0c;而这也带来了共享文件的需求。当我们身处不同的城市&#xff0c;如何高效地共享文件已经成为一项迫切的需求。本文将介绍一种名为“同城异地共享文件”的解决方案&#xff0c;帮助解决这一问题。 2. 天联组网—…

二手物品交易系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;商家管理&#xff0c;用户管理&#xff0c;商品管理&#xff0c;用户咨询管理 商家账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;商品管理&#xff0c;用…

LogicFlow 学习笔记—7. LogicFlow 基础 背景 Background

背景 Background 提供可以修改画布背景的方法&#xff0c;包括背景颜色或背景图片&#xff0c;背景层位于画布的最底层。 info 创建画布时&#xff0c;通过 background 选项来设置画布的背景层样式&#xff0c;支持透传任何样式属性到背景层。默认值为 false 表示没有背景。 …

SAP Web IDE 安装使用

For training SAP Web IDE 是基于 Eclipse 内核的在线开发 IDE&#xff0c;可以使用在线的试用版本&#xff0c;但服务器在德国&#xff0c;访问的网速特别慢。也可以使用 Personal Edition&#xff0c;在本机启动和编写代码。 打开官网下载WEBIDE工具包&#xff0c;包含 Tri…

开源AGV调度系统OpenTCS中的路由器(router)详解

OpenTCS中的任务分派器router详解 1. 引言2. 路由器(router)2.1 代价计算函数&#xff08;Cost functions&#xff09;2.2 2.1 Routing groups2.1 默认的停车位置选择2.2 可选停车位置属性2.3 默认的充电位置选择2.4 即时运输订单分配 3. 默认任务分派器的配置项4. 参考资料与源…

C#——析构函数详情

析构函数 C# 中的析构函数&#xff08;也被称作“终结器”&#xff09;同样是类中的一个特殊成员函数&#xff0c;主要用于在垃圾回收器回收类实例时执行一些必要的清理操作。 析构函数: 当一个对象被释放的时候执行 C# 中的析构函数具有以下特点&#xff1a; * 析构函数只…

简单了解RS485与RS232(UART)

简单了解RS485与RS232&#xff08;UART&#xff09; 一、UART和RS232、RS485的关系1、UART2、RS232/RS4853、RS232 与 RS485 的区别与联系 二、Modbus协议说明1、什么是协议2、Modbus协议说明3、Modebus通信过程4、Modbus存储区5、Modbus协议类型6、Modbus功能码 三、stm32HC-S…

短视频压缩与编码技术在短剧APP小程序开发中的应用:技术选择与工具推荐

在短剧APP小程序开发中&#xff0c;选择合适的短视频压缩与编码技术及工具对于实现高效的视频处理至关重要。本文将探讨如何选择合适的技术和工具&#xff0c;以及推荐一些在实际开发中常用的解决方案。 技术选择的原则 平衡压缩率与视频质量&#xff1a;在选择压缩技术时&…

flutter开发实战-RichText富文本居中对齐

flutter开发实战-RichText富文本居中对齐 在开发过程中&#xff0c;经常会使用到RichText&#xff0c;当使用RichText时候&#xff0c;不同文本字体大小默认没有居中对齐。这里记录一下设置过程。 一、使用RichText 我这里使用RichText设置不同字体大小的文本 Container(de…

Kimichat使用案例013:用kimichat批量识别出图片版PDF文件中的文字内容

文章目录 一、介绍二、具体操作三、信息识别一、介绍 图片版的PDF文件,怎么才能借助AI工具来提取其中全部的文字内容呢? 第一步:将PDF文件转换成图片格式 具体方法参见文章: Kimichat使用案例011:用kimichat将PDF自动批量分割成多个图片(零代码编程) 第二步:识别图片中…

IEC61850 调试工具 工程师必备

文章目录 IEC61850 调试工具 工程师必备主要功能软件截图 IEC61850 调试工具 工程师必备 下载地址&#xff1a;http://www.redisant.cn/iec61850client IEC 61850 是国际电工委员会&#xff08;IEC&#xff09;制定的一项国际标准&#xff0c;主要用于电力系统自动化领域&…

AI引领项目管理新时代:效率与智能并驾齐驱

在数字化浪潮的推动下&#xff0c;项目管理领域正迎来一场由AI技术引领的革新。从自动化任务执行到智能决策支持&#xff0c;AI技术的应用正让项目管理变得更加高效、精准和智能化。本文将探讨项目管理人员及其实施团队如何运用AI技术&#xff0c;以及这些技术如何助力项目管理…

vue3 前端验证码-删除最后一个,焦点聚焦在前一个值上,并不会删除值

删除最后一个数字&#xff0c;焦点聚焦在前一个值上&#xff0c;并不会删除值 <inputv-for"(box, index) in boxes":key"index"ref"inputRefs":value"box"input"onInputChange(index)"keyup"onKeyDown($event, inde…

2、给出五种并行计算机体系结构的名称,并分别画出其典型结构。

①并行向量处理机&#xff08;PVP&#xff09; ②对称多机系统&#xff08;SMP&#xff09; ③大规模并行处理机&#xff08;MPP&#xff09; ④分布式共享存储器多机系统&#xff08;DSM&#xff09; ⑤工作站机群&#xff08;COW&#xff09;

晶振的匹配电容的计算

晶振 等效电路 C0是晶振的静态电容 L1是晶振的等效电感 C1是晶振的等效电容 R1是晶振的等效串联电阻 芯片内部已有反相器和负载电阻 计算公式 参考1 参考2

文件操作(总)

1.为什么使用文件 a是内存上的一块区域 如果程序退出&#xff0c;则内存回收&#xff0c;数据丢失了&#xff0c;再次运行就看不到上次的数据了 为了持久化保存&#xff0c;我们可以使用文件 2.文件是什么 磁盘上的文件是文件 在程序设计中&#xff0c;文件有两种&#xff…

NLP入门——基于TF-IDF算法的应用

从json格式数据中抽出句子和标签 首先查看json格式的数据文件&#xff1a; :~/nlp/tnews/src$ less train.json可以看到json字符串表示一个对象&#xff0c;我们利用json.loads() 函数会将其转换为一个 Python 字典。docs python json #ext.py #encoding: utf-8import sys f…