代码随想录算法训练营第12天—二叉树01 | ● 理论基础 ● *递归遍历 ● *迭代遍历

二叉树

理论基础

文章讲解:https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

  • 二叉树是一种数据结构,常用于递归场景
  • 二叉树:binary tree,每个节点最多有两个子节点(分支),深度为k的二叉树最多有2k-1个节点(k从1开始)
  • 二叉树的常见类型
    • 满二叉树:即节点数达到最大值的二叉树
    • 完全二叉树:除最底层节点外其它层节点均满,最底层节点从左到右连续的二叉树
    • 二叉搜索树:若有左子树,则左子树上所有节点的值比根节点小,若有右子树,则右子树上所有节点的值比根节点大
      • 二叉搜索树
    • 平衡二叉搜索树:左右无子树或左右子树的高度差小于等于1的二叉搜索树
      • 平衡二叉搜索树
  • 二叉树的存储方式
    • 链式存储:通过左右指针存储子节点(相较于顺序存储更易理解,因此更常用)
      • 二叉树链式存储
    • 顺序存储:在内存中连续存储,通常使用数组结构,当前节点i的左子节点为2i+1,右子节点为2i+2
      • 二叉树的顺序存储
  • 二叉树的遍历方式
    • 深度优先遍历:优先往深走,借助栈实现
      • 包括以下三种方式,区别在于把中间节点放在什么顺序,前序就是中左右,中序就是左中右,后序就是左右中
      • 前序遍历(递归法,迭代法)
      • 中序遍历(递归法,迭代法)
      • 后序遍历(递归法,迭代法)
      • 深度优先遍历
    • 广度优先遍历:一层一层地遍历,借助队列实现
      • 层次遍历(迭代法)
  • 二叉树节点结构的定义(这里仅展示链表存储的二叉树结构定义)
class TreeNode:
	def __init__(self, val, left = None, right = None):
		self.val = val
		self.left = left
		self.right = right

*递归遍历(对应力扣144/145/94)(二叉树的深度优先遍历)

题目链接/文章讲解/视频讲解:https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%80%92%E5%BD%92%E9%81%8D%E5%8E%86.html

  • 考点
    • 前序遍历的递归法
    • 中序遍历的递归法
    • 后序遍历的递归法
  • 我的思路
    • 无思路
  • 视频讲解关键点总结
    • 递归代码三要素
      • 参数和返回值是什么
        • 二叉树深度优先遍历的参数为当前节点
        • 返回值为储存结果的列表
      • 递归终止条件是什么
        • 如果当前节点为空,则终止继续搜索,返回一个空列表,之后将开始递归、一层一层将节点储存到列表中
      • 单层递归的逻辑是什么
        • 若为前序遍历(中左右),代码返回值为
          • 当前节点的值(列表形式)
          • +
          • 以当前节点的左子节点为参数调用递归函数的返回值(列表形式)
          • +
          • 以当前节点的右子节点为参数调用递归函数的返回值(列表形式)
        • 若为中序遍历(左中右),代码返回值为
          • 以当前节点的左子节点为参数调用递归函数的返回值(列表形式)
          • +
          • 当前节点的值(列表形式)
          • +
          • 以当前节点的右子节点为参数调用递归函数的返回值(列表形式)
        • 若为后序遍历(左右中),代码返回值为
          • 以当前节点的左子节点为参数调用递归函数的返回值(列表形式)
          • +
          • 以当前节点的右子节点为参数调用递归函数的返回值(列表形式)
          • +
          • 当前节点的值(列表形式)
  • 我的思路的问题
  • 代码书写问题
    • 列表可以直接用+进行拼接,生成一个新列表
  • 可执行代码
# 前序遍历-递归-LC144_二叉树的前序遍历
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return []

        left = self.preorderTraversal(root.left)
        right = self.preorderTraversal(root.right)

        return  [root.val] + left +  right
# 中序遍历-递归-LC94_二叉树的中序遍历
class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        if root is None:
            return []

        left = self.inorderTraversal(root.left)
        right = self.inorderTraversal(root.right)

        return left + [root.val] + right
# 后序遍历-递归-LC145_二叉树的后序遍历
class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return []

        left = self.postorderTraversal(root.left)
        right = self.postorderTraversal(root.right)

        return left + right + [root.val]

*迭代遍历(对应力扣144/145/94)(二叉树的深度优先遍历)

题目链接/文章讲解/视频讲解:https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E8%BF%AD%E4%BB%A3%E9%81%8D%E5%8E%86.html

  • 考点
    • 前序和后序搜索的迭代法实现(使用栈)
  • 我的思路
  • 视频讲解关键点总结
    • 前序(中左右)
      • 首先把根节点加入栈
      • 之后开始循环,循环的终止条件为栈是否为空
      • 循环体内,第一步弹栈,并将弹出节点的值加入储存列表
      • 第二步,如果弹出节点的右子节点不为空,将其压栈
      • 第三步,如果弹出节点的左子节点不为空,将其压栈
      • 继续下一轮循环,直到栈空
      • 返回储存列表
    • 后序(左右中)
      • 首先把根节点加入栈
      • 之后开始循环,循环的终止条件为栈是否为空
      • 循环体内,第一步弹栈,并将弹出节点的值加入储存列表
      • 第二步,如果弹出节点的左子节点不为空,将其压栈
      • 第三步,如果弹出节点的右子节点不为空,将其压栈
      • 继续下一轮循环,直到栈空
      • 返回储存列表的倒序列表
    • 中序(左中右)
      • 中序的迭代遍历思路与前后序有所不同
        • 中序的迭代遍历,所查询的元素和所操作的元素不相同
        • 此时,单纯使用一个栈能做但不好做,因此额外引入一个指针来完善思路
      • 初始指针cur指向根节点,代指所查询的节点;初始栈为空,储存待操作的节点;初始储存列表为空,储存结果(节点的值)
      • 进入while循环,循环条件为指针和栈有一个不为空就继续
      • while循环内,大体的思路是先一直向左查询直到最左节点,之后逐个向回按照左中右的顺序遍历节点;为实现上述操作,需要进行if else条件判断
        • if里负责处理查询到的情况,若cur指针不为空,此时说明查询到了节点,将该节点压栈,并将cur指针指向cur.left;
        • else里负责处理没查询到的情况,如果所查询的节点为空,此时应该开始弹栈,将栈中保存的上一层节点的值遍历储存到储存列表中,因此令cur=弹栈而出的节点,并将cur.val加入储存列表,之后查询cur是否有右子节点(即cur = cur.right)
      • 循环结束,返回储存列表
  • 我的思路的问题
  • 代码书写问题
  • 可执行代码
# 前序遍历-迭代-LC144_二叉树的前序遍历
class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        # 根结点为空则返回空列表
        if not root:
            return []
        stack = [root]
        result = []
        while stack:
            node = stack.pop()
            # 中结点先处理
            result.append(node.val)
            # 右孩子先入栈
            if node.right:
                stack.append(node.right)
            # 左孩子后入栈
            if node.left:
                stack.append(node.left)
        return result
# 后序遍历-迭代-LC145_二叉树的后序遍历
class Solution:
   def postorderTraversal(self, root: TreeNode) -> List[int]:
       if not root:
           return []
       stack = [root]
       result = []
       while stack:
           node = stack.pop()
           # 中结点先处理
           result.append(node.val)
           # 左孩子先入栈
           if node.left:
               stack.append(node.left)
           # 右孩子后入栈
           if node.right:
               stack.append(node.right)
       # 将最终的数组翻转
       return result[::-1]
# 中序遍历-迭代-LC94_二叉树的中序遍历
class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        stack = []  # 不能提前将root结点加入stack中
        result = []
        cur = root
        while cur or stack:
            # 先迭代访问最底层的左子树结点
            if cur:     
                stack.append(cur)
                cur = cur.left		
            # 到达最左结点后处理栈顶结点    
            else:		
                cur = stack.pop()
                result.append(cur.val)
                # 取栈顶元素右结点
                cur = cur.right	
        return result

统一迭代(未做,主要内容是通过栈来实现统一的迭代遍历形式)

题目链接/文章讲解:https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E7%BB%9F%E4%B8%80%E8%BF%AD%E4%BB%A3%E6%B3%95.html

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

获取旁站 / C 段:第三方网站(附链接)

一、介绍 1.1 旁段 在网络安全的上下文中,"旁段"(Pivot)是指攻击者通过入侵一个网络中的一台计算机,然后利用该计算机作为跳板(或者称之为“旁道”)来访问其他计算机或网络资源的行为。 攻击者…

伦敦金交易平台:了解交易背后的世界

伦敦金交易平台是全球金融市场中备受关注的重要平台之一。作为国际金融中心,伦敦汇聚了众多金融机构和投资者,其金交所成为全球最大的现货黄金市场。在这个繁荣蓬勃的市场中,交易活跃,投资机会多样,吸引了众多投资者前…

DDoS攻击激增,分享高效可靠的DDoS防御方案

当下DDoS攻击规模不断突破上限,形成了 "网络威胁格局中令人不安的趋势"。专业数据显示,对比2022年上半年与2023年上半年,所有行业的DDoS攻击频率增加了314%。其中零售、电信和媒体公司遭受的攻击规模最大,三个垂直行业的…

手把手教你激活FL Studio 21.2.2.3914中文破解版2024年图文激活教程以及如何设置中文language

FL Studio 21.2.2.3914软件简介 fl studio 21.2.2.3914中文破解版作为一款极具创意性的音乐软件工作站软件,FL Studio已经成为了许多音乐制作人和音乐爱好者的首选。最新的FL Studio 21.2.2.3914中文破解版的发布,无疑将会引起更多人的关注。 ​ FL St…

NC6X单点登录设计文档说明

前言 因为业务场景需要,第三方系统有些工作需要经常到NC系统里做,如果每次去NC系统做业务单据,都需要反复登录,导致客户使用体验不是很好,所以需要开发实现从第三方系统单点登录到NC系统,提高客户满意度。 …

多维时序 | Matlab实现CNN-RVM卷积神经网络结合相关向量机多变量时间序列预测

多维时序 | Matlab实现CNN-RVM卷积神经网络结合相关向量机多变量时间序列预测 目录 多维时序 | Matlab实现CNN-RVM卷积神经网络结合相关向量机多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现CNN-RVM卷积神经网络结合相关向量机多变量时间序…

快准狠!在3D Slicer中,使用TotalSegmentator扩展可在1分钟内自动分割全身117个器官

本系列涵盖从 3D Slicer 医学图像查看器的基础使用到高级自动分割扩展程序的内容(从入门到高阶!),具体包括软件安装、基础使用教程,自动分割扩展(totalsegmentator, monai label)快速标注数据。 Tina姐:强烈建议做图像分割的宝宝们好好学习,跟着Tina姐涨姿势!本教程…

开关电源学习之Boost电路

如果我们需要给一个输入电压为5V的芯片供电,而我们只有一个3.3V的电源,那怎么办? 我们能不能把3.3V的电压升到5V? 一、电感的简介 而在升压的电路设计方案中,使用到一个重要的元器件:电感。 电感的特性…

44、WEB攻防——通用漏洞RCE代码执行多层面检测利用

文章目录 RCE分类: REC代码执行:引用脚本代码解析执行。例如,eval(phpinfo();)以php脚本解析phpinfo();。RCE命令执行:脚本调用操作系统命令。例如,system(ver),命令执行能执行系统命令。 RCE漏洞对象&am…

C#中实现串口通讯和网口通讯(使用SerialPort和Socket类)

仅作自己学习使用 1 准备部份 串口通讯需要两个调试软件commix和Virtual Serial Port Driver,分别用于监视串口和创造虚拟串口。网口通讯需要一个网口调试助手,网络上有很多资源,我在这里采用的是微软商店中的TCP/UDP网络调试助手&#xff0…

ubuntu下修改hosts读写权限

ubuntu下修改hosts文件的操作: 由于需要在hosts文件下添加ip地址信息,但是初始情况下系统该文件为只读权限无法修改,具体操作如下所示; 1.cd到系统etc目录下,执行如下命令,此时会提示输入密码,直接输入回…

python28-Python的运算符之三目运算符

Python可通过if语句来实现三目运算符的功能,因此可以近似地把这种if语句当成三目运算符。作为三目运算符的f语句的语法格式如下 True_statements if expression else False_statements 三目运算符的规则是:先对逻辑表达式expression求值,如果逻辑表达式…

Java实现数据可视化的智慧河南大屏 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 数据模块 A4.2 数据模块 B4.3 数据模块 C4.4 数据模块 D4.5 数据模块 E 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的数据可视化的智慧河南大屏,包含了GDP、…

学习好并用好大模型

大模型是个好东西,学好并用好益处多多~ 1. 运用大模型服务我们的工作 运用大模型服务于工作,可以从以下几个方面着手: 知识管理与检索: 利用大模型强大的自然语言处理能力,建立企业内部的知识库系统。员工可以通过提问…

python flask 魔术方法

魔术方法作用_init_对象的初始化方法_class_返回对象所属的类_module_返回类所在的模块_mro_返回类的调用顺序,可以找到其父类(用于找父类)_base_获取类的直接父类(用于找父类)_bases_获取父类的元组,按它们…

Flask 入门6:模板继承

1. 一个网站中,大部分网页的模块是重复的,比如顶部的导航栏,底部的备案信息。如果在每个页面中都重复的去写这些代码,会让项目变得臃肿,提高后期的维护成本。比较好的做法是,通过模板继承,把一…

MCU+SFU视频会议一体化,视频监控,指挥调度(AR远程协助)媒体中心解决方案。

视频互动应用已经是政务和协同办公必备系统,早期的分模块,分散的视频应该不能满足业务需要,需要把视频监控,会议,录存一体把视频资源整合起来,根据客户需求,需要能够多方视频互动,直…

Spring Batch 批处理框架适配达梦数据库,实现从文件批量读取写入数据库(完整教程)

效果展示(达梦数据库): 技术简介: Spring Batch 是一个基于 Spring 的批处理框架,用于开发和执行大规模、高性能、可靠的批处理应用程序。它提供了丰富的功能和组件,用于处理复杂的批处理任务,例如大数据ETL(Extract-Transform-Load)、数据清洗、数据迁移、报表生成…

EV1527协议应用

EV1527协议应用 EV1527 帧结构解码原理实现代码 EV1527 帧结构 EV1527 每帧数据由同步码和 24 位的数据码组成,数据码又分为地址码(20 位)和按键码(4 位)。 以 433Mhz EV1527 遥控器为例,遥控波形如下。 …

TOP100 二叉树(二)

7.108. 将有序数组转换为二叉搜索树 给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 示例 1: 输入…
最新文章