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、查看源,删除源&…

elasticsearch结构化搜索

Elasticsearch的结构化搜索(Structured Search)是指对具有明确格式和结构的数据进行搜索的过程。这类数据包括日期、时间、数字、布尔值等,它们都有精确的格式,可以进行逻辑操作,比如比较数值范围或判断值的大小。结构…

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…

css预处理是什么?作用是什么?

CSS预处理器是一种增强和扩展标准CSS的工具。它们允许开发者使用变量、嵌套规则、Mixin&#xff08;混合&#xff09;以及函数等高级功能&#xff0c;以更模块化和可维护的方式编写CSS代码。预处理器如Sass&#xff08;SCSS&#xff09;、Less和Stylus等&#xff0c;通过引入这…

期末复习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. 天联组网—…

hiberfil.sys文件在Windows系统作用

hiberfil.sys文件在Windows系统中起着关键的作用&#xff0c;主要涉及到计算机的休眠功能。以下是关于hiberfil.sys的详细解释&#xff1a; 定义与功能&#xff1a; hiberfil.sys是Windows休眠功能&#xff08;Windows Hibernation&#xff09;将内存数据与会话保存至硬盘所需…

struct易错点

namespace FXTest {class Program{static void Main(string[] args){List<Ast> l1 new List<Ast>();List<IAst> l2 new List<IAst>();l1.Add(new Ast());l2.Add(new Ast());l1[0].id 2;//报错}}interface IAst{}struct Ast:IAst{public int id;} }以…

程序员应该有什么职业素养?Doge

程序员应该有什么职业素养&#xff1f; 1.关爱家人第一&#xff0c;工作第二 2.享受生活第一&#xff0c;工作第二 3.身体健康第一&#xff0c;工作第二 4.取悦自己第一&#xff0c;工作第二

二手物品交易系统的设计

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

C++设计模式----桥接模式

1、介绍 桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#xff0c;它将抽象部分与实现部分分离&#xff0c;使得它们可以独立地变化。桥接模式的核心思想是利用组合关系代替继承关系&#xff0c;将系统划分成多个独立的、功能不同的类层次结构&#xf…

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;主要用于电力系统自动化领域&…