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

news2025/2/24 18:24:30

题目描述

在这里插入图片描述

使用迭代方法解题

class TreeNode {
    var val: Int
    var left: TreeNode?
    var right: TreeNode?
    
    init(_ val: Int) {
        self.val = val
        self.left = nil
        self.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   5

let 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: Int
    var left: TreeNode?
    var right: TreeNode?
    
    init(_ val: Int) {
        self.val = val
        self.left = nil
        self.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   5

let 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.coloradmin.cn/o/1820921.html

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

相关文章

11.第十一章 字典

11. 字典 本章介绍另一种内置类型: 字典. 字典是Python最好的语言特性之一, 它是很多高效而优雅的算法的基本构建块.11.1 字典是一个映射 字典类似于列表, 但更加通用. 在列表中, 下标必须是整数. 而字典的下标(几乎)可以是任意类型. 字典包含下标(称为键)集合和值集合. 每个…

人工智能的前沿技术 博客 期刊 论文 推荐

在学习和关注人工智能的前沿技术时,有几个权威期刊和会议是非常重要的资源。以下是一些推荐的期刊和会议,涵盖了机器学习、深度学习、自然语言处理和生成式AI等领域的最新研究和进展: 博客 Andrej Karpathy’s blog - 深度学习领域知名专家…

在AI云原生时代应该如何应对复杂的算力环境

引言 随着在2019年ChatGPT4的爆火,AI这个之前常常被人觉得非常高深的技术渐渐的被越来越多的人们所了解,越来越多的公司、组织和开发者开始投入AI的使用和开发中来.随着AI和LLM的火热,算力资源也变的越来越紧缺,所以如何高效的管理和使用算力资源也变成了必须要面对的问题。 …

13. 第十三章 案例研究-选择数据结构

13. 案例研究-选择数据结构 到这里尼应该已经学会了Python的核心数据结构, 也见过了一些使用它们的算法. 如果你想要更多地了解算个发可以阅读第21章. 本章配合联系介绍一个案例分析, 帮你思考如何选择数据结构并如何使用它们.13.1 单词频率分析 1. 练习1 编写一个程序, 读入…

【C语言函数实现节选1】

前言: 通过前面的博客,C语言基本知识基本上我已给大家分享完成!接下来我会通过两篇博客结 合前面的知识实现一下常见的函数。实现方式不唯一,大家只要大体思路符合都是可以的,在学习 的过程中尽量自己先实现&#xf…

安装VM虚拟机并创建一个Linux CentOS 7无桌面系统

一、安装vm虚拟机软件 1 下载vm压缩包 百度网盘链接 链接:https://pan.baidu.com/s/1ipiWatBr0wHKMt5c5nQirw?pwdwoy2 提取码:woy2 2.下载完毕后,先将杀毒软件关闭 全部关闭 3. 解压后按照步骤安装即可 按照按照步骤,观看…

C++240613

自由发挥登录窗口的应用场景,实现一个登录窗口界面 要求:每行代码都有注释 #include "my_widget.h"My_Widget::My_Widget(QWidget *parent): QWidget(parent) {//设置窗口的标题this->setWindowTitle("真爱生命,远离赌博&…

Vue31-生命周期的简介

一、需求:文字的透明度递减 示例: 对象的简写形式 new vue({ key:value, key:value, 。。。。。。 }) 二、代码的实现 注意:JS不擅长小数的计算!!! 此写法不好!!!追求…

借力AI,助力网络钓鱼(邮件)检测

引言 互联网时代,邮件系统依然是人们工作、生活中的很重要的一部分,与此同时,邮件系统的发展带来的钓鱼邮件问题也成为网络中的最大的安全隐患之一。本文将为大家解开网络钓鱼(邮件)的神秘面纱,一探究竟&a…

刚刚!彬川机器人社招校招入职Verify测评素质性格测评真题原题题库更新了【含答案】

一、测评环境 温馨提示 1.本次测评包含【素质性格测评】和【Verify测评】两部分,预计用时60min,请确保作答时周围环境无干扰、网络畅通; 2.请使用电脑完成作答,建议使用以下浏览器登录:IE9.0及以上版本,火…

笔记99:OSQP 求解器示例代码

注1:以下代码是 OSQP 的官方文档提供的示例,我加上了详细的注释; 注2:OSQP 库仅支持C语言,不支持C,所以下面的示例代码使用的是C语言;但是 OSQP 求解库提供了针对C的接口 OSQP-EIGEN&#xff1…

免费的端口映射工具哪个好用

端口映射,即从一个网络环境下的端口映射到另一个网络环境下访问的过程。通常由软件方式来提供这一过程的实现,或一些客户端工具。当涉及内外网时,如内网端口地址映射到外网地址,即是内网穿透的原理。免费的端口映射工具有哪些&…

C++设计模式——Decorator装饰器模式

一,装饰器模式简介 装饰器模式是一种结构型设计模式, 它允许在不改变现有对象的情况下,动态地将功能添加到对象中。 装饰器模式是通过创建具有新行为的对象来实现的,这些对象将原始对象进行了包装。 装饰器模式遵循开放/关闭原…

对补码的理解:两种求法

课本的结论是:二进制数的最高位是符号位。符号位为 0 表示正数和 零 ,符号位为 1 表示负数。 正数是原码反码补码都是一样的。负数的反码是:符号位不变,剩下位取反。 负数的补码是:符号位不变,剩下位取反&a…

u-boot(四)-顶层目录链接脚本文件(u-boot.lds)介绍

一,IMX6ULL映像文件 1,格式概述 对于IMX6ULL,烧写在EMMC、SD/TF卡上的程序,并不能“自己复制自己”,是“别人把它复制到内存里”。一上电首先运行的是boot ROM上的程序,它从EMMC、SD/TF卡上把程序复制进内…

妙用OSGraph:发掘GitHub知识图谱上的开源故事

作者:范志东 1. 何为OSGraph? OSGraph (Open Source Graph) 是一个开源图谱关系洞察工具,基于GitHub开源数据全域图谱,实现开发者行为、项目社区生态的分析洞察。可以为开发者、项目Owner、开源布道师、社区运营等提供简洁直观的…

电脑自带录屏在哪?电脑录屏,4个详细方法

在现代社会中,越来越多的人需要在电脑上录制视频,比如录制游戏操作、制作教学视频、演示文稿等等。因此,电脑录屏成为了一项非常重要的功能。那么电脑自带录屏在哪?本文将带领大家看看可以使用哪些方法进行录屏。 录屏方法一&…

SK海力士计划于2024年第四季度启动GDDR7大规模生产

SK海力士,作为HBM市场的领头羊,于6月13日宣布,公司目标于2024年第四季度开始其GDDR7芯片的大规模生产。 与此同时,美光科技在Computex展会上也宣布推出其GDDR7图形内存,目前正处于样品测试阶段。据AnandTech报道&#…

Python | Leetcode Python题解之第149题直线上最多的点数

题目&#xff1a; 题解&#xff1a; class Solution:def maxPoints(self, points: List[List[int]]) -> int:n len(points)if n < 2:return nres 2for i in range(n):x1, y1 points[i][0], points[i][1]has {}for j in range(i 1, n):x2, y2 points[j][0], points…

AI虚拟试穿技术:开启高保真、多场景、多样化服装组合的试穿应用

随着电子商务的快速发展,消费者对于在线购物体验的要求越来越高。特别是在服装领域,消费者渴望能够在购买前直观地了解服装的试穿效果。传统的虚拟试穿技术虽然已有一定的发展,但在不同场景下的高保真度和鲁棒性方面仍面临挑战。为此,我们研发了一种全新的AI虚拟试穿技术,…