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 = val
        self.left = left
        self.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 = cur
                    print(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

 

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

 

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

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

相关文章

马云最新发声:AI时代刚刚到来,一切才刚开始,我们正当其时!

大家好,我是木易,一个持续关注AI领域的互联网技术产品经理,国内Top2本科,美国Top10 CS研究生,MBA。我坚信AI是普通人变强的“外挂”,所以创建了“AI信息Gap”这个公众号,专注于分享AI全维度知识…

原码一位乘法

王道考研ppt总结: 个人理解: 原码一位乘法: 结果符号的确定:符号位异或,很好理解 数值位绝对值相乘 小数的乘法: 小学乘法的规则是:乘数的每一位和被乘数进行相乘,然后作为数积&…

labelImg将图像标签显示到界面

打开View的显示类别 但是颜色不够清晰,我想自己定制 我的象棋红色和黑色两种。并且把字体方法一些。 可以看到 color self.select_line_color if self.selected else self.line_color参考:https://blog.csdn.net/qq_41082953/article/details/10330225…

如何使用 ArcGIS Pro 制作热力图

热力图是一种用颜色表示数据密度的地图,通常用来显示空间分布数据的热度或密度,我们可以通过 ArcGIS Pro 来制作热力图,这里为大家介绍一下制作的方法,希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的POI数…

Gitlab全量迁移

Gitlab全量迁移 一、背景1.前提条件 一、背景 公司研发使用的Gitlab由于服务器下架需要迁移到新的Gitlab服务器上。Gitlab官方推荐了先备份然后再恢复的方法。个人采用官方的另外一种方法,就写这篇文章给需要的小伙伴参考。 源Gitlab: http://old.mygitlab.com #地…

vue2创建项目的两种方式,配置路由vue-router,引入element-ui

提示:vue2依赖node版本8.0以上 文章目录 前言一、创建项目基于vue-cli二、创建项目基于vue/cli三、对吧两种创建方式四、安装Element ui并引入五、配置路由跳转四、效果五、参考文档总结 前言 使用vue/cli脚手架vue create创建 使用vue-cli脚手架vue init webpack创…

leetCode第十题 : 正则表达式匹配 动态规划【10/1000 python】

👤作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。 会一些的技术:数据分析、算法、SQL、大数据相关、python 欢迎加入社区:码上找工作http://t.csdnimg.cn/Q59WX 作者专栏每日更新: LeetCode…

软考120-上午题-【软件工程】-软件开发模型02

一、演化模型 软件类似于其他复杂的系统,会随着时间的推移而演化。在开发过程中,常常会面临以下情形:商业和产品需求经常发生变化,直接导致最终产品难以实现;严格的交付时间使得开发团队不可能圆满地完成软件产品&…

Docker安装nacos教程

目录 1.首先拉取nacos镜像2.启动容器,3.查看容器id4.复制容器内的 /home/nacos目录下的logs,data,conf目录到容器外(docker cp 后的容器id可以缩略写前几位)5.进入上一步操作的conf目录,修改目录下的application.properties的文件…

FORM的引入与使用

FORM的引入与使用 【0】引入 ​ 表单(Form)是网页中用于收集用户输入数据的一种交互元素。通过表单,用户可以输入文本、选择选项、上传文件等操作。表单通常由一个或多个输入字段(Input Field)组成,每个字…

【重磅推荐】2024七大零售行业线下开店超全指南大全共452份

如需下载完整PPTX可编辑源文件,请前往星球获取:https://t.zsxq.com/19F4dDDrv 联华快客便利店的加盟手册.docx 好德便利店加盟手册.docx 超市&便利店守则:商品退换货管理.docx 赠品管理制度.doc 选址必看.doc 新人续签考核作业.doc 物流箱管理制度.d…

第04章 计算机常用通信指标和术语视频课程

4.1 本章目标 掌握bit、Byte、KB、MB、GB、TB概念和换算关系掌握波特率、比特率、误码率的概念掌握信道、基带信号、频带信号概念了解多路复用、频分多路复用、时分多路复用了解同步传输、异步传输概念 4.2 bit、Byte、KB、MB、GB、TB概念和换算关系 4.2.1 概念与换算 4.2.2…

SinoDB备份恢复工具之dbexport/dbimport

dbexport和 dbimport是两个简单的备份恢复实用程序,无需任何提前配置即可运行。这两个实用程序可以在不同平台的SinoDB数据库服务器之间迁移数据,可以使用它们备份和还原小型数据库。 1. dbexport命令语法 dbexport以文本格式导出数据库中所有对象的模式…

ENSP防火墙配置VRRP负载分担[图片配置步骤],VRRP简介

配置目标 1.实现同一区域设备分别走两条线路进行通信 2.当一侧线路故障时切换至备份线路 拓扑搭建 配置接口地址及安全区域 fw1: fw2: 配置安全策略 fw1/fw2 配置默认路由 fw1: fw2: 配置IP-link fw1 fw2 配置vrrp FW1&am…

OpenHarmony开发技术:【国际化】实例

国际化 如今越来的越多的应用都走向了海外,应用走向海外需要支持不同国家的语言,这就意味着应用资源文件需要支持不同语言环境下的显示。本节就介绍一下设备语言环境变更后,如何让应用支持多语言。 应用支持多语言 ArkUI开发框架对多语言的…

机器学习和深度学习-- 李宏毅(笔记与个人理解)Day8

Day 8 classification :Probabilistic Generative Model 今天上了一整天的课, 本来实在是更新不动了,但是看到《剑来》更新了,想一想这本书里面一直强调的成功的feature – 心性,嗯心性坚毅就好!主人公陈平…

实战项目——智慧社区(二)之 物业管理

分页 用于分页封装的实体类 Data public class PageVO {private Long totalCount;private Long pageSize;private Long totalPage;private Long currPage;private List list; }分页的相关配置 package com.qcby.community.configuration;import com.baomidou.mybatisplus.e…

乡村智慧化升级:数字乡村打造农村生活新品质

目录 一、乡村智慧化升级的内涵与意义 二、乡村智慧化升级的具体实践 1、加强农村信息基础设施建设 2、推广智慧农业应用 3、提升乡村治理智慧化水平 4、丰富智慧乡村生活内容 三、数字乡村打造农村生活新品质的成果展现 1、农业生产效率与质量双提升 2、农民收入与消…

OSCP靶场--Peppo

OSCP靶场–Peppo 考点(ident枚举服务用户名ssh登陆rbash绕过 docker提权) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.158.60 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-10 09:32 EDT Nmap scan report…

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

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