代码随想录算法训练营第十四天(py)| 二叉树 | 递归遍历、迭代遍历、统一迭代

news2025/1/14 1:04:08

1 理论基础

1.1 二叉树的种类

满二叉树

只有度为0和2的节点,且度为0的节点在同一层。
深度为k,有2^k-1个节点
满二叉树

完全二叉树

除了最底层可能没填满,其余每层节点数都达到最大。并且最底层节点全部集中在左边。
在这里插入图片描述

二叉搜索树

是一个有数值的有序树。左子树的所有节点均小于根节点,右子树的所有节点均大于根节点。
在这里插入图片描述
大的放右边,小的放左边。

平衡二叉搜索树。

若非空,则左右两个子树的高度差不超过1,并且两个子树都是平衡二叉树
在这里插入图片描述

1.2 二叉树的存储

链式存储

用指针。一般用这个
在这里插入图片描述

顺序存储

用数组
在这里插入图片描述
若父节点的数组下标为i,则左子节点下标为2i+1,右子节点下标为2i+2。

1.3 二叉树的遍历方式

深度优先遍历:往深里走,直到碰到叶子节点。
-前序遍历:中左右
-中序遍历:左中右
-后序遍历:左右中
广度优先遍历:一层一层走
在这里插入图片描述
python下的树定义:

class TreeNode:
	def __init__(self, val, left=None, right=None):
		self.val = val # 值
		self.left = left # 左指针
		self.right = right # 右指针

2 递归遍历

每次写递归要按照以下三要素来写:

  1. 确定递归函数的参数和返回值。
  2. 确定终止条件
  3. 确定单层递归的逻辑

2.1 前序递归(中左右)

# 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]:
    	res = []
    	def dfs(node):
    		if node is None:
    			return
    		res.append(node.val)
    		dfs(node.left)
    		dfs(node.right)
    	dfs(root)
    	return res

2.1 中序递归(左中右)

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
    	res = []
    	def dfs(node):
    		if node is None:
    			return
    		dfs(node.left)
    		res.append(node.val)
    		dfs(node.right)
    	dfs(root)
    	return res

2.3 后序递归(左右中)

class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
    	res = []
    	def dfs(node):
    		if node is None:
    			return
    		dfs(node.left)
    		dfs(node.right)
		    res.append(node.val)
	    dfs(root)
    	return res

3 迭代遍历

需要创建一个数组res用于保存结果,和一个栈stack用于保存当前节点。迭代中有两个操作:

  1. 处理当前节点:将元素放入res中
  2. 遍历节点

3.1 前序迭代遍历(中左右)

先将根节点压栈,然后右子节点压栈,然后左子节点压栈
注意:这里和中左右的顺序是相反的!因为这么做出栈的时候才是正确的顺序

# 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]:
    	stack = [root]
    	res = []
    	if root == None:
    		return res
    	while stack: # 当栈非空时
    		node = stack.pop()
    		res.append(node.val) # 中结点先处理
    		if node.right: # 右孩子先入栈
    			stack.append(node.right)
    		if node.left:  # 左孩子后入栈
    			stack.append(node.left)
    	return res

3.2 中序迭代遍历(左中右)

中序迭代遍历的代码不与前序的通用,因为处理顺序和访问顺序不一样。

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
    	res = []
    	stack = [] # 不能提前将root放入stack
    	cur = root # 当前节点
  	    if root == None:
    		return res
    	while cur or stack: # 当当前节点和栈有一个非空时
    		if cur != None:
    			stack.append(cur)
    			cur = cur.left  # 先一直靠左深入
    		else: # 当左边走到头了,处理栈顶节点
    			cur = stack.pop()
    			res.append(cur.val) # 中
    			cur = cur.right # 右
    	return res
    	

3.3 后序迭代遍历(左右中)

调整前序遍历的顺序即可,将res反转。
注意,反转前res的顺序为中右左,因此入栈的顺序应该左孩子先入栈,右孩子后入栈。

class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
    	res = []
    	stack = [root]
		if root == None:
    		return res
    	while stack:
    		node = stack.pop()
    		res.append(node.val)
    		if node.left:
    			stack.append(node.left)# 左孩子先入栈
    		if node.right:
    			stack.append(node.right)# 右孩子后入栈
    	return res[::-1] #反转

4 统一迭代

其实针对三种遍历方式,使用迭代法是可以写出统一风格的代码。
就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。要处理的节点放入栈之后,紧接着放入一个空指针作为标记。

4.1 前序遍历(中左右)

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
    	res = []
    	stack = [root]
    	if root == None:
    		return res
    	while stack:
    		if node != None:
    			if node.right:
    				stack.append(node.right)
    			if node.left:
    				stack.append(node.left)
    			stack.append(node) # 把访问的节点和要处理的节点都入栈
    			stack.append(None) # 并且在要处理的节点之后添加一个空值
    		else:
    			node = stack.pop()
    			res.append(node.val)
    	return res

4.2 中序遍历(左中右)

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
    	res = []
    	stack = [root]
    	if root == None:
    		return res
    	while stack:
    		node = stack.pop()
    		if node != None:
    			if node.right:
    				stack.append(node.right)
    			stack.append(node)
    			stack.append(None)
    			if node.left:
    				stack.append(node.left)
    		else:
    			node = stack.pop()
    			res.append(node.val)
    	return res

4.3 后序遍历(左右中)

class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
    	res = []
    	stack = [root]
    	if root == None:
    		return res
    	while stack:
    		node = stack.pop()
    		if node != None:
    			stack.append(node)
    			stack.append(None)
    			if node.right != None:
    				stack.append(node.right)
    			if node.left != None:
    				stack.append(node.left)
    		else:
    			node = stack.pop()
    			res.append(node.val)
    	return res

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

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

相关文章

【class14】人工智能初步之语音识别

【class14】 从本节课开始,我们将一起踏入语音识别的世界,学习这些知识点,为自己的视频匹配上字幕:1. 语音识别2. 采样率3. 创建语音识别应用4. 创建语音识别SDK客户端 人类的自然语言可分为两种形态:1.语音&#xff…

Python使用pymysql操作数据库

大家好,当涉及到与数据库进行交互和操作时,Python的pymysql库是一个常用且功能强大的选择。pymysql提供了与MySQL数据库的连接、查询、插入、更新和删除等操作的方法,使得在Python中进行数据库操作变得简单而高效。 1、安装 pymysql 库 在开…

python判断字符串是否为回文串的详细解析与实现

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、引言:回文串的定义与背景 二、判断回文串的基本思路 示例解析 三、代码实…

LabVIEW和ZigBee无线温湿度监测

LabVIEW和ZigBee无线温湿度监测 随着物联网技术的迅速发展,温湿度数据的远程无线监测在农业大棚、仓库和其他需环境控制的场所变得日益重要。开发了一种基于LabVIEW和ZigBee技术的多区域无线温湿度监测系统。系统通过DHT11传感器收集温湿度数据,利用Zig…

【ARK Survival Evolved】方舟:生存进化一键使用服务器开服联机教程

1、进入控制面板 2、第一次购买服务器会安装游戏端,大约5分钟左右,如果长时间处于安装状态请联系客服 3、设置游戏端口 方舟生存进化的设置需要三个端口,它们用于游戏端口(必须为首选端口),查询端口&#…

html5 笔记02

目录 01 svg的基本使用 02 svg绘图 03 进程和线程 01 svg的基本使用 svg和canvas的区别: canvas: 1.canvas作为一个容器只有一个dom元素 ,内部元素无法使用dom操作 (canvas不能展开然后选择不到 svg查看元素能选中因为是通过标签控制的) 2.canvas 是配合js完成各种绘制效果 …

【学习笔记】Webpack5(Ⅱ)

Webpack 3、高级篇 3.1、提升开发体验 —— SourceMap 3.2、提升打包速度 3.2.1 HotModuleReplacement 3.2.2 OneOf 3.2.3 Include / Exclude 3.2.4 Cache 3.2.5 Thread 3.3、减少代码体积 …

iMX6ULL 嵌入式linux开发 | 4G无线广播终端实现方案介绍

现有的有线广播,如村上的大喇叭,需要布线,施工麻烦。借助现有的4G网络,传输音频流完全没问题,4G网络结合流媒体技术和MQTT消息传递实现设备间的同步推拉流。这种方案可以避免有线布线的麻烦,同时实现4G无线…

Spark在YARN上运行图解(资源调度+任务调度)及案例

前提:已经安装了spark集群,可参考上篇文章搭建:http://t.csdnimg.cn/UXBOp 一、Spark集群配置YARN 1、增加hadoop 配置文件地址 vim spark-env.sh 增加export HADOOP_CONF_DIR/usr/local/soft/hadoop-3.1.1/etc/hadoop 2、关闭虚拟内存 cd …

DMR对讲机数字协议详解

一、概述 DMR数字对讲机协议是欧洲电信标准协会在2005年4月推出的数字对讲机标准,后来又进行了多次修改。最新版本DMR数字对讲机协议是2007年12月公布的,共有四部分:第一部分为空中接口物理层和数据链路层协议,第二部分为空中接口…

【Unity AR开发插件】四、制作热更数据-AR图片识别场景

专栏 本专栏将介绍如何使用这个支持热更的AR开发插件,快速地开发AR应用。 链接: Unity开发AR系列 插件简介 通过热更技术实现动态地加载AR场景,简化了AR开发流程,让用户可更多地关注Unity场景内容的制作。 “EnvInstaller…”支…

牛客网刷题 | BC93 公务员面试

目前主要分为三个专栏,后续还会添加: 专栏如下: C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读! 初来乍到,如有错误请指出,感谢! 描述 公务员面试现场打分…

【安装笔记-20240520-Windows-在 QEMU 中尝试运行 OpenWRT】

安装笔记-系列文章目录 安装笔记-20240520-Windows-在 QEMU 中尝试运行 OpenWRT 文章目录 安装笔记-系列文章目录安装笔记-20240520-Windows-在 QEMU 中尝试运行 OpenWRT 前言一、软件介绍名称:OpenWRT主页官方介绍 二、安装步骤测试版本:openwrt-23.05…

C语言在VS中使用scanf报错?

我们在使用VS时,用scanf函数,VS会报以下错误: 以下是解决方法: 来到输出窗口,复制以下语句:_CRT_SECURE_NO_WARNINGS 第一种暂时方法 1.在代码的第一行,写下:#define _CRT_SECURE_…

vuejs路由和组件系统

前端路由原理 createRouter * hash* window.addEventListener(hashChange)* 两种实现路由切换的模式:UI组件(router-link,router-view),Api(push()方法) * history * HTML5新增的API &#xff0…

2024年电工杯A题论文首发+摘要分享+问题一代码分享

问题一论文代码链接:https://pan.baidu.com/s/1kDV0DgSK3E4dv8Y6x7LExA 提取码:sxjm --来自百度网盘超级会员V5的分享 园区微电网风光储协调优化配置 摘要:园区微电网由风光发电和主电网联合为负荷供电,为了尽量提高风光电量的…

机器人运动轨迹学习——GMM/GMR算法

机器人运动轨迹学习——GMM/GMR算法 前置知识 GMM的英文全称为:Gaussian mixture model,即高斯混合模型,也就是说,它是由多个高斯模型进行混合的结果:当然,这里的混合是带有权重概念的。 一维高斯分布 GMM中…

鸿蒙布局List简介

鸿蒙布局List简介 List--常见的布局容器List 创建方式创建方式一,通过Listitem创建方式二,通过ForEach和Listitem创建方式三,通过ListItemGroup List–常见的布局容器 List是在app开发中最常见的一种布局方式,例如通讯录、新闻列…

Vue3实现简单的瀑布流效果,可抽离成组件直接使用

先来看下效果图: 瀑布流中的内容可进行自定义,这里的示例图是通过不同背景颜色的展示进行区分,每个瀑布流中添加了自定义图片和文字描述。 实现方式: 1.建立子组件(可单独抽离)写出瀑布流的样式 文件名为…

远程桌面连接不上远程服务器,如何有效的解决远程桌面连接不上远程服务器的问题

在解决远程桌面连接不上远程服务器的问题时,我们需要采取一种专业且系统的方法来排查和修复可能存在的故障。以下是一些建议和步骤,帮助用户更有效地解决此类问题。 首先,用户需要确认远程服务器的状态和网络连接是否正常。 这包括检查服务器…