2024.4.8Morris中序遍历(线索二叉树)学习

这次博主在学习完知识点和代码之后,准备对这个知识重新进行整理总结。站在一个初学者的角度来看待这个知识点,在他人的讲解基础上加一点点自己的理解,并记录下来。以加深自己的理解,并且希望能够帮助到你。博主是一个初学者,若有不对请友善指出,大家一起学习进步。

一、知识点讲解

这里简单地进行说明。

1.为什么使用Morris中序遍历

树的递归使用的是栈这个数据结构来存储节点,以达到记录前驱节点的目的。而过多的内容很可能导致栈溢出。为了压缩空间(降低空间复杂度),所以我们使用Morris中序遍历,能够将空复降至O(1)。(结尾学习视频有更详细的原理解释)

2.什么是Morris中序遍历

既然递归中使用栈的原因是想记录前驱节点,那么我们只要达到记录前驱节点的目的即可不使用栈。

首先,它的本质还是中序遍历。

正常的中序遍历,在“递”左子树时是可以直接通过左指针到达,但是在“归”根节点的时候是没有办法直接到达的(右子树只用“递”,不用“归”)。而“归”的时候均是到达叶子节点才“归”,则可以充分利用叶子节点的左右空指针,将右空指针指向根节点,这样就可以直接“归”到根节点。

其中,为什么是右空节点呢?博主认为,因为根节点是叶子节点的后继节点,而中序遍历遍历完本节点下一个就遍历右节点,所以用叶子节点的右空节点指向根节点。

下面结合图进行理解:

0861f12048d748a8923dc2938a61d921.jpeg

其中,序号是按照中序遍历的顺序编号的,方便大家观看。

而红色的线就是我们需要增加的指针,称为线索(也是线索二叉树的由来)。

基本原理理解了,那我们就来看看代码是什么实现的。

二、代码及分析

1.实现代码

代码参考文章末尾学习视频。博主为代码添加了部分注释:

from typing import Optional# Definition for a binary tree node.
class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = right
class Solution:def MorrisInorderTraversal(self, root: Optional[TreeNode]):# 本质是中序遍历cur = root# 遍历节点while cur:# 没有左子树# 当前节点就没有中序遍历前驱节点,直接进入右边if not cur.left:cur = cur.right# 有左子树# 找cur的中序遍历前驱节点# 通俗讲,前驱在左节点最右边else:pre = cur.left  # 左节点# 到最右边while pre.right and pre.right != cur:pre = pre.right# 跳出循环两种情况# 情况一:到达最右边# 建立线索if pre.right is None:pre.right = curprint(f"设置线索:{pre}->{cur}")# 继续遍历左边# 中序是遍历完左子树再遍历根cur = cur.left# 情况二:遍历完左子树,进行回溯# 如果没有建立线索的二叉树是不会出现pre.right == cur的# 说明此处已经建立了线索,已经遍历过了# 线索二叉树的回溯是通过线索回溯的else:pre.right = None    # 删掉线索,还原二叉树print(f"删掉线索:{pre}->{cur}")# 左边已经遍历完了,遍历右边cur = cur.right

下面对我当时看到代码时产生的疑问进行解答:

问:为什么会有回溯过程?

答:它是一步一步进入左子树进行遍历的。如先进入root的左节点找前驱,再去root.left的左节点找前驱,那么叶子节点已经被建立联系了。当到达叶子节点时,无左节点,在进入右节点时会通过之间建立好的线索进行回溯到上一个节点,再重复建立过程,相当又要经历建立好的线索进行回溯。进而回溯到根节点(每个节点)再进入右子树进行遍历。

另外,删掉线索的那一行代码是可以注释掉的,这样就可以得到遍历后的树,而不是只是经历过程。

下面结合图片对过程进行理解,主要是理解过程,不必死磕过程。在博主的眼中,树是抽象且局部重复的,我们只需要关注局部,理解对局部的操作即可。

e5860b833f6e4873ac944bfef9166b4e.jpeg

2.对代码进行测试

写完一个代码还是需要对代码进行测试。作为一个初学者,我觉得记录下测试的方法还是很有必要的。 

(1)首先要初始化树

学习链接:http://t.csdnimg.cn/P1wB7

具体初始化代码就不写了,对学习链接代码进行修改即可。(ps:需要对树类名,和左右指针名进行修改哦)

另外,其中的运行结果在哪里查看呢?博主搜索后发现在Debug处查看。需要在操作后断点,断点如下:

482301620eb94e1c95d576066ce685dd.png

(2)对初始化后的树使用函数即可,再断点查看就行了(如上图第二处断点,记得注释掉删除线索的那一行代码)。

三、使用Morris中序遍历

练习题目:501. 二叉搜索树中的众数

博主是在遇到这道题时才来学习的这个方法,可以通过这道题来练习一下。

四、学习和参考视频

【【算法奇淫技】第1期  Morris遍历(二叉树的特殊遍历法)】 https://www.bilibili.com/video/BV13J411z7Z5/?share_source=copy_web&vd_source=dc0e55cfae3b304619670a78444fd795

 

感谢你看到这里!一起加油吧!

 

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

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

相关文章

HeidiSQL下载安装使用

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

互联网需要做安全防护吗?

互联网需要做安全防护,因为网络攻击的风险随时存在。一旦遭受大规模攻击,企业很可能会受到严重影响,甚至会造成巨大的经济损失和品牌声誉受损。因此,建议企业在安全防护方面做好以下几点: 加强网络安全意识教育&#x…

设备基础命令,路由基础

直连路由 静态路由 动态路由 根据路由器学习路由信息、生成并维护路由表的方法包括直连路由(Direct)、静态路由(Static)和动态路由(Dynamic)。直连路由:路由器接口所连接的子网的路由方式称为直连路由;非直连路由:通过路由协议从别的路由器…

2024年4月12日 十二生肖 今日运势

小运播报:2024年4月12日,星期五,农历三月初四 (甲辰年戊辰月丙午日),法定工作日。 红榜生肖:羊、狗、虎 需要注意:牛、马、鼠 喜神方位:西南方 财神方位:…

“安全边际大师”卡拉曼2023年珍贵访谈:如果视市场为狂躁的交易对手,那你就能利用反复无常来获利

“对于那些被广泛跟踪的股票,如果你不比其他人更聪明,且你的观点与别人无异,你是赚不到钱的。” “足够大的折价也许可以抵消你对它缺乏最深刻的认识。” “拓宽投资视野不仅诱人,也可能价值连城。” “如果向市场寻求答案&…

欢迎加入PenPad Season 2 ,获得勋章以及海量 Scroll 生态权益

PenPad 是 Scroll 生态中的首个 LaunchPad 平台,该平台继承了 Scroll 生态的技术优势,具备包括隐私在内的系列特点,同时且也被认为是 Scroll 生态最重要的价值入口之一。Penpad 与 Scroll 官方始终保持着合作,同时该项目自启动以来…

基于Springboot的网上商品订单转手系统(有报告)。Javaee项目,springboot项目。

演示视频: 基于Springboot的网上商品订单转手系统(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系…

无人机概述

1、中英文对照表 中文中文简称英文全称英文简称无人驾驶飞机无人机Unmanned Aerial VehicleUAV无人机自组织网络无人机网络flying Ad-Hoc networkFANET 2、相关概念 2.1鲁棒性 网络鲁棒性是指网络系统在面对随机故障、蓄意攻击或其他异常情况时,能够保持其基本功…

智慧工地管理平台源码:提供专业落地的解决方案

目录 智慧工地平台功能简介 一、劳务实名制系统 二、智能塔吊可视系统 三、视频监控(含安全行为识别) 四、环境监测(联动自动喷淋) 五、起重机械管控(含吊钩可视化) 六、升降电梯智能管控 七、高支…

鸿蒙让我赚到了第一笔桶金!年薪33.6W!

抢人!抢人!抢人! 所谓抢滩鸿蒙,人才先行。鸿蒙系统火力全开后,抢人已成鸿蒙市场的主题词! 智联招聘数据显示,春节后首周,鸿蒙相关职位数同比增长163%,是去年同期的2.6倍…

【C++算法】线性DP详解:数字三角形、最长上升子序列、最长公共子序列、最长公共子串、字符串编辑距离

文章目录 1)数字三角形1:顺推2:逆推 2)最长上升子序列1:线性DP做法2:二分优化 3)最长公共子序列4)最长公共子串5)字符串编辑距离 1)数字三角形 1&#xff1a…

股票高胜率的交易法则是什么?

股票交易中的高胜率交易法则并非一成不变,而是根据市场状况、个人投资风格和经验等多种因素综合而定的。以下是一些有助于提升交易胜率的法则和策略: 1.趋势跟踪法则:在股票交易中,趋势跟踪是一种有效的策略。通过观察大盘和个股…

Hadoop安装部署-NameNode高可用版

Hadoop分布式文件系统支持NameNode的高可用性,本文主要描述NameNode多节点高可用性的安装部署。 如上所示,Hadoop分布式文件系统部署了NameNode的Master主节点以及NameNode的Slave副节点,当Master主节点发生故障变得不可用时,ZooK…

llama-factory SFT系列教程 (一),大模型 API 部署与使用

文章目录 背景简介难点 前置条件1. 大模型 api 部署下一步阅读 背景 本来今天没有计划学 llama-factory,逐步跟着github的文档走,发现这框架确实挺方便,逐渐掌握了一些。 最近想使用 SFT 微调大模型,llama-factory 是使用非常广泛…

python之文件操作与管理

1、文件操作 通过open()操作,来创建文件对象,下面是open()函数语法如下: open(file,mode r,buffering -1 , encoding None ,errors None , newline None,closefd True,opener …

Python(3):条件语句+循环语句+逻辑运算符+符号优先级

文章目录 一、if语句1.if语句2.if 和 elif区别3.三元表达式 二、循环语句1.range函数和循环结束关键字2.while循环3.for循环 三、逻辑运算符1.and语句2.or语句3.not语句4.逻辑运算法的优先级 四、python运算符优先级和结合性一览表 一、if语句 1.if语句 1.if单分支语句 格式…

Python项目1 外星人入侵_外星人

在本章中,我们将在游戏《外星人入侵》中添加外星人。首先,我们在屏幕上边缘附近添加一个外星人,然后生成一群外星人。我们让这群外星人向两边和下面移 动,并删除被子弹击中的外星人。最后,我们将显示玩家拥有的飞船数量…

从路由器syslog日志监控路由器流量

路由器是关键的网络基础设施组件,需要随时监控,定期监控路由器可以帮助管理员确保路由器通信正常。日常监控还可以清楚地显出通过网络的流量,通过分析路由器流量,安全管理员可及早识别可能发生的网络事件,从而避免停机…

算法训练营第二十三天(二叉树完结)

算法训练营第二十三天(二叉树完结) 669. 修剪二叉搜索树 力扣题目链接(opens new window) 题目 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>L) 。你可能需要改…

SQLite数据库在Linux系统上的使用

SQLite是一个轻量级的数据库解决方案,它是一个嵌入式的数据库管理系统。SQLite的特点是无需独立的服务器进程,可以直接嵌入到使用它的应用程序中。由于其配置简单、支持跨平台、服务器零管理,以及不需要复杂的设置和操作,SQLite非…