遍历二叉树的Morris序

news2024/12/23 0:47:00

参考书:《程序员代码面试指南》

这种方法的好处在于,它做到了时间复杂度为O(n),额外空间复杂度为O(1)(只申请几个变量就可以完成整个二叉树的遍历)。

Morris遍历时cur访问节点的顺序就是morris序,可以在Morris序的基础上加工出前序遍历序列、中序遍历序列、后序遍历序列。
对于前序、中序,你只需要看要在Morris遍历过程中的合适位置加打印动作即可。
而对于后序,比较复杂。
下面举个例子,说明Morris遍历和对应的加工。
在这里插入图片描述
在这里插入图片描述
对于上图的二叉树来说,Morris序就是 cur访问过的顺序:1,2,4,2,5,1,3,6,3,7.
前序遍历序列就是第一次访问的顺序:1,2,4,5,3,6,7。
中序遍历序列就是第二次访问(附注:如果一个节点只被访问一次,那么第一次访问时直接打印)的顺序:4,2,5,1,6,3,7。
后序遍历序列是,每次恢复现场(恢复空闲指针)时,逆向打印cur的左子树的右边界;最后,逆序打印整个树的右边界,下面给出详细说明:
第一次恢复现场时,cur=②,逆向打印其左树的右边界:4;
第二次恢复现场时,cur=①,逆向打印其左树的右边界:5,2;
第三次恢复现场时,cur=③,逆向打印其左树的右边界:6;
最后,逆序打印整个树的右边界:7,3,1;
所以,整个后序遍历序列是 4,5,2,6,7,3,1.

public class Morris {

    public void morris(TreeNode head){// morris遍历
        TreeNode cur=head;
        TreeNode rightMost=null;
        while (cur!=null){
            rightMost=cur.left;
            if(rightMost!=null){
                while (rightMost.right!=null&&rightMost.right!=cur){
                    rightMost=rightMost.right;

                }

                if(rightMost.right==null){
                    rightMost.right=cur;
                    cur=cur.left;
                    continue;
                }

                if(rightMost.right==cur){
                    rightMost.right=null;
                    cur=cur.right;
                    continue;
                }
            }else {
                cur=cur.right;
            }

        }


    }

    public static void morrisPreTraversal(TreeNode head){
        TreeNode cur=head;
        TreeNode rightMost=null;
        while (cur!=null){
            rightMost=cur.left;
            if(rightMost!=null){
                while (rightMost.right!=null&&rightMost.right!=cur){
                    rightMost=rightMost.right;

                }

                if(rightMost.right==null){
                    rightMost.right=cur;
                    System.out.println(cur.value);
                    cur=cur.left;
                    continue;
                }

                if(rightMost.right==cur){
                    rightMost.right=null;
                    cur=cur.right;
                    continue;
                }
            }else {
                System.out.println(cur.value);
                cur=cur.right;
            }

        }
    }

    public static void morrisInTraversal(TreeNode head){
        TreeNode cur=head;
        TreeNode rightMost=null;
        while (cur!=null){
            rightMost=cur.left;
            if(rightMost!=null){
                while (rightMost.right!=null&&rightMost.right!=cur){
                    rightMost=rightMost.right;

                }

                if(rightMost.right==null){
                    rightMost.right=cur;

                    cur=cur.left;
                    continue;
                }

                if(rightMost.right==cur){
                    rightMost.right=null;
                    System.out.println(cur.value);
                    cur=cur.right;
                    continue;
                }
            }else {
                System.out.println(cur.value);
                cur=cur.right;
            }

        }
    }

    public static void morrisPostTraversal(TreeNode head){
        TreeNode cur=head;
        TreeNode rightMost=null;
        while (cur!=null){
            rightMost=cur.left;
            if(rightMost!=null){
                while (rightMost.right!=null&&rightMost.right!=cur){
                    rightMost=rightMost.right;

                }

                if(rightMost.right==null){
                    rightMost.right=cur;

                    cur=cur.left;
                    continue;
                }

                if(rightMost.right==cur){
                    rightMost.right=null;
                    printReverseRB(cur.left);
                    cur=cur.right;
                    continue;
                }
            }else {

                cur=cur.right;
            }

        }
        printReverseRB(head);
    }

    private static void printReverseRB(TreeNode head) {
        TreeNode next=null;
        TreeNode cur=head;
        TreeNode pre=null;

        pre=reverseEdge(cur);
        cur=pre;
        while (cur!=null){
            System.out.println(cur.value);
            cur=cur.right;
        }
        // restore
        reverseEdge(pre);
    }
    private static TreeNode reverseEdge(TreeNode head){
        TreeNode next=null;
        TreeNode cur=head;
        TreeNode pre=null;
        while (cur!=null){
            next=cur.right;
            cur.right=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }

    public static void main(String[] args) {
        TreeNode head=new TreeNode(1);
        head.left=new TreeNode(2);
        head.right=new TreeNode(3);
        head.left.left=new TreeNode(4);
        head.left.right=new TreeNode(5);
        head.right.left=new TreeNode(6);
        head.right.right=new TreeNode(7);

        morrisPreTraversal(head);
        System.out.println();
        morrisInTraversal(head);
        System.out.println();
        morrisPostTraversal(head);

    }



}

class TreeNode{
    TreeNode right;
    TreeNode left;
    int value;
    public TreeNode(int val){
        this.value=val;
        this.right=null;
        this.left=null;
    }
}


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

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

相关文章

大模型系列:OpenAI使用技巧_在文本向量化的交易数据做多标签分类

本笔记本涵盖了数据未标记但具有可用于将其聚类为有意义的类别的特征的用例。聚类的挑战在于使那些使得这些聚类突出的特征可读,这就是我们将使用GPT-3生成有意义的聚类描述的地方。然后,我们可以使用这些描述来为以前未标记的数据集应用标签。 为了向模…

大数据技术16:数据湖和湖仓一体

前言:近几年大数据概念很多,数据库和数据仓库还没搞清楚,就又出了数据湖,现在又开始流行湖仓一体。互联网公司拼命造高大上概念来忽略小白买单的能力还是可以的。 1、数据库 数据库是结构化信息或数据的有序集合,一般以…

分享一款超强大的抖音数据采集工具

你好,我是坚持分享干货的 EarlGrey,翻译出版过《Python编程无师自通》、《Python并行计算手册》等技术书籍。 如果我的分享对你有帮助,请关注我,一起向上进击。 创作不易,希望大家给一点鼓励,把公众号设置为…

轮廓检测与处理

轮廓检测 先将图像转换成二值 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度图 ret, thresh cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 变为二值,大于127置为255,小于100置为0.使用cv2.findContours(thresh, cv2.RETR_TREE, cv2.…

【Unity入门】热更新框架之xLua

目录 一、xLua概述1.1xLua简介1.2xLua安装 二、Lua文件加载2.1执行字符串2.2加载Lua文件2.3自定义loader 三、xLua文件配置3.1打标签3.2静态列表3.3动态列表 四、Lua与C#交互4.1 C#访问Lua4.1.1 获取一个全局基本数据类型4.1.2 访问一个全局的table4.1.3 访问一个全局的functio…

【Unity美术】Unity工程师对3D模型需要达到的了解【一】

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:Uni…

机器学习之K-means聚类

概念 K-means是一种常用的机器学习算法,用于聚类分析。聚类是一种无监督学习方法,它试图将数据集中的样本划分为具有相似特征的组(簇)。K-means算法的目标是将数据集划分为K个簇,其中每个样本属于与其最近的簇中心。 以下是K-means算法的基本步骤: 选择簇的数量(K值)…

算法分析与设计基础

一、绪论 1.算法的概念及特征 1.1 定义: 算法是指求解某个问题或是某类问题的一系列无歧义的指令,也就是说,对于符合一定规范的输入,能够在有限时间内获得所要求的输出。 1.2 特征: 输入:算法中的各种运…

Prometheus通过consul实现自动服务发现

环境,软件准备 本次演示环境,我是在虚拟机上安装 Linux 系统来执行操作,以下是安装的软件及版本: System: CentOS Linux release 7.6Docker: 24.0.5Prometheus: v2.37.6Consul: 1.6.1 注意:这里为了方便启动 Prometheus、Consul服…

电容器50ZLH56MEFC6.3X11

电容器 常用电子元器件类型 50ZLH56MEFC6.3X11 文章目录 电容器前言一、电容器二、50ZLH56MEFC6.3X11总结前言 电容器在电子电路中有许多重要的应用,如滤波、耦合、储能、定时等。不同类型的电容器具有不同的性能特点,例如电容量、工作电压、频率响应等。在选择和使用电容…

const变量真的不能修改吗?

文章目录 1 在Linux系统下1.1 系统参数1.2 通过指针修改(编译器有警告) 2 在Windows下2.1 系统参数2.2 直接修改2.3 指针间接修改2.4 指针间间接修改 3 总结: 1 在Linux系统下 1.1 系统参数 内核:Linux version 3.2.0-24-generi…

Glary Utilities Pro - 电脑系统优化全面指南:详尽使用教程

软件简介: Glary Utilities Pro 是一款全面的电脑优化工具,它旨在帮助用户提升计算机的性能和稳定性。这款软件提供了多种功能,包括系统清理、优化、修复以及保护。通过一键扫描,它可以识别并清除无用文件、临时数据、注册表错误等…

关于“Python”的核心知识点整理大全50

目录 python_repos.py 17.1.6 概述最受欢迎的仓库 python_repos.py 17.1.7 监视 API 的速率限制 注意 17.2 使用 Pygal 可视化仓库 python_repos.py 17.2.1 改进 Pygal 图表 python_repos.py 往期快速传送门👆(在文章最后)&#xf…

SAP问题 OPEN SQL 取不到值

关键:数据库中有数据,但是open sql取不到数据 背景: 标准程序在测试环境正常执行,在生产环境报错。 解决过程: 第一步:分析执行结果不一致可能的原因: 1.测试数据问题,可能性小&…

openGauss学习笔记-178 openGauss 数据库运维-逻辑复制-逻辑解码-使用SQL函数接口进行逻辑解码

文章目录 openGauss学习笔记-178 openGauss 数据库运维-逻辑复制-逻辑解码-使用SQL函数接口进行逻辑解码178.1 前提条件178.2 操作步骤 openGauss学习笔记-178 openGauss 数据库运维-逻辑复制-逻辑解码-使用SQL函数接口进行逻辑解码 openGauss可以通过调用SQL函数,…

传奇私服教程,新手小白速速下载!

传奇私服教程,新手小白速速下载! 第二十课-封玩家账号登陆-封玩家机器码登陆.zip 第十九课-快速搭建FTP服务器教程配套工具.zip 第十八课-绿盟GOM1108引擎登陆器配置防劫持列表教... 第十七课-最新访问网站自动弹出加群教程.zip 修复沙城捐献不了或者捐献…

Mybatis行为配置之Ⅳ—日志

专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL Mybatis配置入门 Mybatis行为配置之Ⅰ—缓存 Mybatis行为配置…

Python FastApi连接oracle进行查询

这边技术选型是cx_oracle进行连接查询,cx_oracle的使用首先要有官方的客户端才能连接到数据库,python并不自带客户端。我用是Python3.9 安装客户端 可以到官网在选择最新版进行下载。 Instant Client for Microsoft Windows (x64) 64-bit 或者直接从我…

uniapp多级动态表单规则

最近有个新的业务、主要涉及多层级的动态表单提交,其中又涉及很多类型,踩了很多坑之后,终于研发完毕。 传来的数据格式处理 传来的数据格式涉及比较多的内容,以下举例一个,涉及到规则的填写 规则写法有两种&#xff…

【Maven】下载及配置

文章目录 1. 下载2. 解压3. 配置环境变量4. 验证 Maven 是一个跨平台的项目管理工具。作为 Apache 组织的一个颇为成功的开源项目,其主要服务于基于 Java 平台的项目创建,依赖管理和项目信息管理,是一个自动化构建工具,本文将介绍…