首页 > 其他分享 >Morris遍历

Morris遍历

时间:2024-02-26 11:02:37浏览次数:18  
标签:遍历 TreeNode cur mostRight Morris right null root

Morris遍历

基本模板

注意业务逻辑书写的位置:
一般为:第一次访问节点。第二次访问节点。右子树为空。遍历完成。

/**
 * Morris遍历 模板
 */
public void morris(TreeNode root) {
    TreeNode cur = root;
    while (cur != null) {
        // cur 左子树不为空
        if (cur.left != null) {
            TreeNode mostRight = cur.left;
            while (mostRight.right != null && mostRight.right != cur) {
                mostRight = mostRight.right;
            }
            if (mostRight.right == null) {
                // 第一次访问 cur
                // ... do something
                mostRight.right = cur;
                cur = cur.left;
            } else {
                // 第二次访问 cur
                // ... do something
                mostRight.right = null;
                cur = cur.right;
            }
        } else {
            // cur 左子树为空
            // ... do something
            cur = cur.right;
        }
    }
    // 遍历完成时
}

Morris - 前序

规则:
如果一个节点只能被访问一次,被访问时打印。
如果一个节点能被访问两次,在第一次被访问时打印。

代码

public void morrisNLR(TreeNode root) {
    TreeNode cur = root;
    while (cur != null) {
        // cur 左子树不为空
        if (cur.left != null) {
            TreeNode mostRight = cur.left;
            while (mostRight.right != null && mostRight.right != cur) {
                mostRight = mostRight.right;
            }
            if (mostRight.right == null) {
                // 第一次访问 cur
                System.out.println(cur.val);
                // ... do something
                mostRight.right = cur;
                cur = cur.left;
            } else {
                // 第二次访问
                mostRight.right = null;
                cur = cur.right;
            }
        } else {
            // cur 左子树为空
            System.out.println(cur.val);
            // ... do something
            cur = cur.right;
        }
    }
}

Morris - 中序

规则:
如果一个节点只能被访问一次,被访问时打印。
如果一个节点能被访问两次,在第二次被访问时打印。

public void morrisLNR(TreeNode root) {
    TreeNode cur = root;
    while (cur != null) {
        // cur 左子树不为空
        if (cur.left != null) {
            TreeNode mostRight = cur.left;
            while (mostRight.right != null && mostRight.right != cur) {
                mostRight = mostRight.right;
            }
            if (mostRight.right == null) {
                // 第一次访问 cur
                // ... do something
                mostRight.right = cur;
                cur = cur.left;
            } else {
                // 第二次访问 cur
                System.out.println(cur.val);
                // ... do something
                mostRight.right = null;
                cur = cur.right;
            }
        } else {
            System.out.println(cur.val);
            // ... do something
            cur = cur.right;
        }
    }
}

Morris - 后序

规则:
如果一个节点能被访问两次,在第二次被访问时自底向上打印该节点左子树的右边界。
当所有节点遍历完后,单独自底向上打印整棵树的右边界

public void morrisLRN(TreeNode root) {
    TreeNode cur = root;
    while (cur != null) {
        // cur 左子树不为空
        if (cur.left != null) {
            TreeNode mostRight = cur.left;
            while (mostRight.right != null && mostRight.right != cur) {
                mostRight = mostRight.right;
            }
            if (mostRight.right == null) {
                // 第一次访问 cur
                // ... do something
                mostRight.right = cur;
                cur = cur.left;
            } else {
                mostRight.right = null;
                
                // ... do something
                // 访问第二次时逆序打印左子树的右边界
                printRightEdge(cur.left);
                
                cur = cur.right;
            }
        } else {
            cur = cur.right;
        }
    }
    printRightEdge(root);
}

/**
 * 自底向上打印以root为根的右边界
 */
public void printRightEdge(TreeNode root) {
    TreeNode tail = reverseRightEdge(root);
    TreeNode cur = tail;
    while (cur != null) {
        System.out.println(cur.val);
        cur = cur.right;
    }
    reverseRightEdge(tail);
}

public TreeNode reverseRightEdge(TreeNode root) {
    TreeNode pre = null, next;
    while (root != null) {
        next = root.right;
        root.right = pre;
        pre = root;
        root = next;
    }
    return pre;
}

标签:遍历,TreeNode,cur,mostRight,Morris,right,null,root
From: https://www.cnblogs.com/annamaple/p/18033844

相关文章

  • powershell遍历文件获取字段列表
    #指定要搜索的文件夹路径和正则表达式关键字$folderPath="C:\myapp\"$table_list="tblBOM,tblTest"$tables=$table_list.Split(',')foreach($tablein$tables){$regexPattern_field="$table\.(\w+......
  • 二叉树查找树遍历
    二叉树查找树遍历存放规则:小的存左边、大的存右边、一样的不存前序、中序、后序指的是当前结点的顺序前序:当前结点、左子节点、右子节点中序:左子节点、当前节点、右子节点后序:左子节点、右子节点、当前结点前序遍历中左右遍历完左树遍历右树从上到下,根节点->从左......
  • Go 中如何高效遍历目录?探索几种方法
    Go中如何高效遍历目录?探索几种方法原创波罗学码途漫漫2024-02-2108:01上海听全文图片嗨,大家好!我是波罗学。本文是系列文章Go技巧第十八篇,系列文章查看:Go语言技巧。如果对我的文章感兴趣,欢迎关注我的公众号: 目录遍历是一个很常见的操作,它的使用场景有如文件目录查......
  • bs4遍历文档树
    数据准备:#导入模块frombs4importBeautifulSoup#查询数据文本html_doc="""<html><head><title>TheDormouse'sstory</title></head><body><pclass="title"id='id_xx'xx='zz'&......
  • 遍历用for还是foreach?
    在C#中,for和foreach都是用来遍历集合或数组的常见循环结构。每种循环都有其适用的场景和优缺点。下面我们将通过一些例子来详细比较这两种循环。1.使用for循环for循环在C#中通常用于需要明确控制循环次数或需要访问集合索引的场景。int[] numbers = { 1, 2, 3, 4, 5 ......
  • 代码随想录算法训练营第十八天 | 112. 路径总和,113. 路径总和ii ,106.从中序与后序遍
     513.找树左下角的值 已解答中等 相关标签相关企业 给定一个二叉树的 根节点 root,请找出该二叉树的 最底层最左边 节点的值。假设二叉树中至少有一个节点。 示例1:输入:root=[2,1,3]输出:1示例2:输入:[1,2,3,4,null,5,6,n......
  • N叉树遍历模板
    N叉树(N-aryTree)的类型和代码模板与二叉树有些相似,但由于N叉树具有多个子节点,因此在遍历和节点定义上有所不同。以下是N叉树的类型和相应的代码模板:N叉树节点的定义:classNode:def__init__(self,val=None,children=None):self.val=valself.children......
  • 代码随想录算法训练营第十五天 | 层次遍历 | 101. 对称二叉树 | 226.翻转二叉树
    226.翻转二叉树 已解答简单 相关标签相关企业 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例1:输入:root=[4,2,7,1,3,6,9]输出:[4,7,2,9,6,3,1]示例2:输入:root=[2,1,3]输出:[2,3,1]示例3:输入:root=[]输出:[......
  • 力扣递归 广度优先搜索之102. 二叉树的层序遍历
    classSolution{   List<List<Integer>>result=newArrayList<>();   publicList<List<Integer>>levelOrder(TreeNoderoot){       if(root==null){           returnresult;       }       traverse(root,0);    ......
  • (18/60)找树左下角的值、路径总和、从中序与后序遍历构造二叉树
    找树左下角的值leetcode:513.找树左下角的值层序迭代法思路层序遍历,每次更新result为每层最左侧元素。复杂度分析时间复杂度:遍历,O(N)。空间复杂度:队列层序遍历,树*似完全二叉树时O(N),树极倾斜时O(logN)。注意点略代码实现/***Definitionforabinarytreenode.......