基本题型记录-二叉树中序遍历

由于本人基础较差,所以针对部分题型做一个记录,以免自己忘记

1、二叉树中序遍历

这个遍历方法可以搜一下博客上很多讲解,这里主要是记录一下代码实现,以下面的二叉树为例子
在这里插入图片描述

结果应该是
在这里插入图片描述

2、迭代法

2.1 遍历过程

这里借用了一个临时的栈(先访问的后处理),存储对应的根节点以及左子树对应的节点,整个过程基本上是不断访问子树(先左,后根,然后右),将根节点推入栈,当访问到最后一个根节点的左子树节点为空时,从栈顶取出对应元素,再访问其右子树节点,判断其是否有左右子树再进行操作。

  1. 从根节点(23)开始,curr开始指向原始根节点
    在这里插入图片描述

  2. 指向根节点元素(23)压入栈中(根节点往往后面才会处理,所以我们先将其放入栈底)
    在这里插入图片描述

  3. 找到当前节点的左子树节点(34),curr=curr.left
    在这里插入图片描述

  4. 当前移动后的curr(指向34)不为空的话,则将其推入栈中
    在这里插入图片描述

  5. 继续找当前节点(34)的左子节点(方法同上一个节点,若不为空则推入栈中)
    在这里插入图片描述
    在这里插入图片描述

  6. 直到左子树节点为空(即图示所示77对应的节点左子节点为空),取对应栈顶元素
    此时说明该节点无左子树,根据中序遍历左跟右的顺序,左子树为空,此时应该读取根节点元素(即取出对应的栈顶元素),这里77即为我们中序遍历的第一个节点
    在这里插入图片描述

  7. 访问77对应右子树节点
    为空则说明这个节点对应无右子树,那么也就不用访问其对应右节点
    在这里插入图片描述
    至此,以77为根节点的左子树访问完毕

  8. 访问以77作为左子节点的根节点99(从栈中取出对应根节点,栈顶元素99)
    访问完栈顶元素以后,一定紧接着访问右子树
    在这里插入图片描述

  9. 访问以99为根节点的右子树,若其不为空,则压入栈中作为右子树的根节点
    在这里插入图片描述

  10. 查询以90为根节点的右子树是否有左子节点
    在这里插入图片描述
    如果以90为根节点的右子树有左子节点,那么方法同上,依次访问下去
    如果没有左子节点,那么取出栈中的90这个根节点
    在这里插入图片描述

  11. 查询以90为根节点的子树是否有右子树
    在这里插入图片描述
    此时以90为根节点的子树右子树节点为空,那么接下来进一步访问栈中所存的对应根节点元素

  12. 继续读取栈顶元素(此时对应34)
    在这里插入图片描述
    此时,以34为根节点的左子树我们已经处理完毕了,34这个根节点也读取了,那么接下来处理34对应的右子树。

  13. 读取以34为根节点的右子树
    以34为根节点的右子树为空,那么以34为根节点的子树遍历完毕
    在这里插入图片描述
    接下来继续处理栈中元素

  14. 继续读取栈中元素(此时为23)
    在这里插入图片描述
    此时,整颗二叉树的左子树都遍历完成,接下来遍历对应的右子树

  15. 遍历右子树根节点(根节点为23对应右子树根节点不为空,可继续遍历,先遍历第一个根节点21,并且压入栈中)
    在这里插入图片描述
    在这里插入图片描述

  16. 继续先遍历以21为根节点的左子树,不为空则继续压入栈中(45)
    在这里插入图片描述

  17. 继续左移,直到有一个左子树为空
    指向为空时(45的左子节点),开始处理栈顶元素,读取栈顶元素
    在这里插入图片描述
    在这里插入图片描述

  18. 查询以45为根节点的左子树是否有右子节点
    若有则推入栈中,查询接下来是否有左子节点
    若无则说明以45为根节点的子树访问完毕,接下来继续处理栈顶元素
    在这里插入图片描述

  19. 观察以21为根节点的右子树情况,curr=curr.right
    在这里插入图片描述
    右子树根节点不为空(60),则推入栈中
    在这里插入图片描述

  20. 观察以60为根节点的右子树是否还有左右节点
    若有左子节点则继续遍历
    若无左子节点则取出栈顶元素(60),开始遍历右子树。
    若右子节点不为空,则推入栈中继续遍历
    若右子节点为空,且栈为空时,则整个中序遍历结束
    在这里插入图片描述

2.2 代码实现

代码前面的说明直接拷贝了力扣的内容,函数的主要思想是
从根节点遍历二叉树,如果根节点为空,则直接返回空list
接下来是正常流程(整个流程走完同上面的遍历过程)

  1. 新建两个list,一个作为栈存储栈顶元素,一个存储最终的遍历结果
  2. curr开始指向根节点
  3. 遍历的结束条件是当前指针为空并且栈中没有元素(这里的while循环条件)
  4. 将根节点推入栈中,节点指针左移
  5. 当左移后的节点指针为空时,说明以该节点为根节点的子树无左子节点,遍历顺序为左根右,那么左为空,中序遍历则直接读取其栈顶元素(根节点的值),指针也指向该根节点,跳出第二个while循环。
  6. 查询以上一步中为根节点为子树的右子节点,移动指针,继续重复上述遍历(进到第一个while循环)
  7. 直至指针指向为空,且栈中无元素时,结束中序遍历

2.2.1 python

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):def inorderTraversal(self, root):""":type root: TreeNode:rtype: List[int]"""if not root:return []res, stack = list(), list()curr = rootwhile curr or len(stack): # 指针为空且栈中元素为空时结束循环while curr: # 当前指针不为空,推入根节点stack.append(curr)curr = curr.left# 左子节点为空,则读取栈顶元素对应的根节点node = stack.pop()res.append(node.val)# 读取右子树curr = node.rightreturn res

这里给的用例是
输入:[1,null,2,3]
输出:[1,3,2]
这里我打印了最初的根节点:
(TreeNode{val: 1, left: None, right: TreeNode{val: 2, left: TreeNode{val: 3, left: None, right: None}, right: None}}, 'root')
在这里插入图片描述

2.2.2 JavaScript

/*** Definition for a binary tree node.* function TreeNode(val, left, right) {*     this.val = (val===undefined ? 0 : val)*     this.left = (left===undefined ? null : left)*     this.right = (right===undefined ? null : right)* }*/
/*** @param {TreeNode} root* @return {number[]}*/
var inorderTraversal = function(root) {if (!root) return []const stack = [], res = []let curr = rootlet nodewhile (!(!stack.length && !curr)) { // 指针为空且栈中无元素时,结束循环// while (stack.length || curr) {while (curr) { // 指针不为空stack.push(curr)curr = curr.left}node = stack.pop()res.push(node.val)curr = node.right}return res
};

3、递归法

3.1 遍历过程

  1. 拆分二叉树
    在这里插入图片描述
    主要思想是将一个完整的二叉树,分成左子树、根节点、右子树
    在这里插入图片描述
    进一步继续拆分
    在这里插入图片描述
    当最左边的左子树其左子节点为空则结束递归

  2. 进一步从最小的子树依次访问
    在这里插入图片描述

  3. 依次进行遍历
    在这里插入图片描述
    中序遍历=中序遍历左子树+根节点+中序遍历右子树

3.2 代码实现

/*** Definition for a binary tree node.* function TreeNode(val, left, right) {*     this.val = (val===undefined ? 0 : val)*     this.left = (left===undefined ? null : left)*     this.right = (right===undefined ? null : right)* }*/
/*** @param {TreeNode} root* @return {number[]}*/
var inorderTraversal = function(root) {if (!root) return []const inorder = (node, res) => {if (!node) returninorder(node.left, res)res.push(node.val)inorder(node.right, res)}const res = []inorder(root, res)return res
};

参考链接

力扣讲解

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

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

相关文章

C++算法二叉树中序遍历

非递归中序遍历二叉树思路(借助栈实现): 1、依次将所有左子节点压栈,直至为空; 2、弹出栈顶元素,访问栈顶,将栈顶的右子节点压栈,返回步骤1; 3、直至栈空。 (…

详解二叉树的中序遍历

中序遍历:首先遍历左子树,然后访问根节点,最后遍历右子树(左->根->右) 中序遍历的递归算法 思路: 遍历左子树访问根节点遍历右子树 代码如下: //二叉树的中序遍历(递归&a…

二叉树的中序遍历算法

一,简介 二叉树的中序遍历在计算机行业有着重要的作用,其中一个应用就是判断一棵二叉树是否二叉排序树。 下面介绍递归和非递归两种方式实现中序遍历。 二,递归实现 递归实现非常简单,左根右依次进行即可。 void mid_scan2(n…

二叉树中序遍历的三种方法

二叉树是一种重要的数据结构,对二叉树的遍历也很重要。这里简单介绍三种二叉树中序遍历的方法。二叉树的中序遍历就是首先遍历左子树,然后访问当前节点,最后遍历右子树。对于下面的二叉树,中序遍历结果如下: 结果&…

(数据结构)二叉树中序遍历

二叉树中序遍历 二叉树中序遍历的实现思想是: 访问当前节点的左子树访问根节点访问当前节点的右子树 图 1 二叉树 以上图 1 为例,中序遍历的过程如下: 访问该二叉树的根节点,找到 1遍历节点 1 的左子树,找到节点 2遍…

二叉树的先序、中序、后序以及层次遍历

二叉树的先序、中序、后序以及层次遍历 方法:在遍历二叉树的时候,一个节点的遍历我们把它看做要经过它三次(下图红色区域)。 当经过一次,被写出来的点,我们称它为先序遍历。 当经过两次,被写出来的点,我…

(数据结构)二叉树后序遍历

二叉树后序遍历 二叉树后序遍历的实现思想是: 访问当前节点的左子树访问当前节点的右子树访问根节点 图 1 二叉树 以上图 1 为例,后序遍历的过程如下: 从根节点 1 开始,遍历该节点的左子树(以节点 2 为根节点&#…

二叉树的中序遍历

二叉树文章系列: 二叉树的前序遍历二叉树的中序遍历二叉树的后序遍历二叉树的层序遍历二叉树的前序、中序、后序、层序遍历【解法完整版】 本文目录 一、解题思路:递归二、解题思路:迭代 二叉树的中序遍历的记忆法则是“左根右"&#x…

MySQL基础- 多表查询 和 事务

目录 多表查询多表关系多表查询概述多表查询的分类内连接外连接自连接联合查询union,union all子查询标量子查询列子查询行子查询表子查询 综合练习小结 事务事务简介事务的操作四大特性ACID并发事务问题事务的隔离级别小结 多表查询 之前的SQL语句里的DQL只能进行…

【C++入门】什么是引用

目录 一、引用概念 二、引用特性 三、常引用 四、使用场景 1. 做参数 2. 做返回值 五、传值,传引用效率比较 六、引用和指针的区别 一、引用概念 引用不是新定义一个变量,而是给已存在变量取一个别名,编译器不会为引用变量开辟内存空间…

C++ 函数对象 详解

目录 🤔函数对象: 🤔本质: 🤔特点: 代码示例: 运行结果: 🤔 内置函数对象: 1.算数仿函数 代码示例: 运行结果: 2.关系仿函数 …

华为OD机试真题B卷 Java 实现【字符串分隔】,附详细解题思路

一、题目描述 输入一个字符串,请按长度为8拆分每个输入字符串并进行输出,长度不是8整数倍的字符串请在后面补数字0,空字符串不处理。 二、输入描述 连续输入字符串(每个字符串长度小于等于100)。 三、输出描述 依次输出所有分割后的长度…

如何查看Steam的17位Id

方法/步骤 1、点击左上角Stream中的设置 2、 进入后点击“界面”,勾选“当可用时显示steam URL 地址栏”。 3、最后点击“查看个人资料”后17位即为ID。

steam注册模拟注册

代替手动模拟注册steam帐号

账号的注册

给账号注册,主要是给数据库中添加一个账号类数据,如图是以userName为用户名和password为密码的数据列表: 给用户和密码添加新的数据就是一个基础的账号注册,下面是页面的主要内容代码样式: 给相应的元素赋予name值&…

Steam注册遇到CAPTCHA问题,一直注册不了,一个简单的注册办法

这个问题一直解决不了 后来我就用了V.P.eN翻墙在Google Chrome上粘贴进入网址再注册就巨快 我自己用的一个很简洁,好用免费的VPeN叫白鲸 V.P.eN下载网址:https://www.bjch110.com/?mid1003 下载安装都很简单 然后白鲸显示连接上后,就打开Goo…

怎样注册邮箱账号?

邮箱账号的注册可以按照以下2种途径: 一、Web端注册 1、网页端搜索:http://163.net,点击“立即注册” 2、4个邮箱套餐,可以根据自己的使用情况进行选择 3、填写申请的邮箱账号&输入密码,手机号码,完…

Unity账号注册

Unity账号注册 文章目录 Unity账号注册 先找到Unity官网 看图: ##基本信息填入 : 密码格式: 用户名错误提示 用户名已存在: 用户名无效(可能含有特殊字符或特殊字符串): ##验证信息 账号注册有两种验证方法:…

Steam注册到交易

Steam注册到交易 Steam注册到交易 Steam注册到交易Steam注册注册邮箱下载steam和网易UU加速注册Steam 手机令牌绑定 Steam注册 注册邮箱 163网易免费邮–中文邮箱第一品牌 申请一个你喜欢的邮箱名字和你的手机号就注册好你的邮箱啦。 下载steam和网易UU加速 大概是在这里…

IMX6ULL裸机篇之I2C相关寄存器

一. I2C实验 I2C时钟选择与传输速率 1. IMX6ULL的 I2C频率标准模式 100kbit/S,快速模式为 400Kbit/S 2. 时钟源选择 perclk_clk_rootipg_clk_root66MHz(由之前的时钟实验章节可以知道是 66MHz)。 二. I2C 寄存器配置 I2Cx_IFDR寄存器&…