Morris遍历

简介: 二叉树递归遍历的实质是,只要这个节点不为空,那么这个节点一定会遍历3次,先序中序后续只不过是打印的时机不同。先序是第一次到达这个节点,中序是第二次,后序是第三次。

二叉树递归遍历的实质是,只要这个节点不为空,那么这个节点一定会遍历3次,先序中序后续只不过是打印的时机不同。先序是第一次到达这个节点,中序是第二次,后序是第三次。Morris遍历高度模仿这个过程。Morris遍历,如果这个节点有左子树,那么能到达这个节点两次,没有左子树,只能到达这个节点一次。Morris遍历的时间复杂度为O(n),空间复杂度为O(1)。


img_7c5205ce157c7e7421f452f628e13795.jpe
morris.jpg

Morris遍历的规则如下

  • 来到的当前节点记为cur(引用), 如果cur无左孩子,cur向右移动,cur = cur.right。
  • 如果cur有左孩子,找到cur左子树最右的节点,记作mostRight
    1)如果mostRight的right指针指向空,让其指向cur,cur向左移动
    (cur = cur.left)。
    2)如果mostRight的right指针指向cur,让其指向空,cur向右移动。

然后,值得注意的是,Morris遍历可以写成二叉树的先中后,相关的方法会在代码中注释

public class MorrisTraversal {

    public static  class Node{
        public int value;
        public Node left;
        public Node right;

        public Node(int value){
            this.value = value;
        }
    }

    //morris遍历
    public void morris(Node head){
        if(head == null)
            return;
        Node cur = head;
        Node mostRight = null;
        while(cur != null){
            mostRight = cur.left;
            //左孩子不为空的情况
            if(mostRight != null){
                //找到最右的节点
                while(mostRight.right != null && mostRight.right != cur)
                    mostRight = mostRight.right;

                if(mostRight.right == null){
                    mostRight.right = cur;
                    cur = cur.left;
                    continue;
                }else {
                    mostRight.right = null;
                }
            }
            System.out.print(cur.value + " ");
            cur = cur.right; //左孩子为空,直接向右移动
        }
        System.out.println();
    }

    //Morris前序遍历
    public void morrisPre(Node head){
        if(head == null)
            return;
        Node cur = head;
        Node mostRight = null;
        while(cur != null){
            mostRight = cur.left;
            //左孩子不为空的情况
            if(mostRight != null){
                //找到最右的节点
                while(mostRight.right != null && mostRight.right != cur)
                    mostRight = mostRight.right;

                if(mostRight.right == null){
                    mostRight.right = cur;
                    System.out.print(cur.value + " ");
                    cur = cur.left;
                    continue;
                }else {
                    mostRight.right = null;
                }
            }else {
                System.out.print(cur.value + " ");
            }
            
            cur = cur.right; //左孩子为空,直接向右移动
        }
        System.out.println();
    }


    
    //后面的太复杂了,暂时先放着。。。
    //Morris中序遍历


    //Morris后续遍历

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

目录
相关文章
|
25天前
|
C#
C# 循环遍历使用
C# 循环遍历使用
29 0
|
6月前
|
算法 C++
87 C++ - 常用遍历算法
87 C++ - 常用遍历算法
20 0
|
4月前
|
JavaScript 小程序
遍历类数组之获取多个dom节点并遍历
遍历类数组之获取多个dom节点并遍历
|
5月前
各种遍历方法以及注意点
各种遍历方法以及注意点
19 0
|
8月前
|
存储 算法
二叉树的创建和遍历
二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分
65 0
|
10月前
链表的遍历
链表的遍历
|
11月前
逆序遍历List集合
逆序遍历List集合
42 0
|
12月前
|
机器学习/深度学习 C++ 容器
二叉树创建和遍历(C++实现)
树(Tree)是n(n≥0)个节点的有限集。在任意一棵树中有且仅有一个特定的称为根(Root)的节点;当n>1时,其余节点可分m(m>0)为个互不相交的有限集T1,T2,...,Tm;其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)。 二叉树(Binary Tree)是一种特殊的有序树型结构,所有节点最多只有2棵子树。
451 0
|
存储 机器学习/深度学习 缓存
链表和有序二叉树插入元素时真的比数组快吗?
公司有位C++标准委员会的顾问大佬,一年会有几次视频讲座,分享一些编程要点或者经验。很多时候都是C++很基础的方面,但是他的讲解视频真的很深入浅出,有时候会“打破”一些理所应当的观点,这篇文章就是让我觉得很有趣,并且意想不到的地方,在这里分享一下。
链表和有序二叉树插入元素时真的比数组快吗?
|
存储 机器学习/深度学习 人工智能
关于哈密顿路是否存在的遍历算法
我是怎么也没想到这个问题陪伴了我快十年的时光,占到了我生命的一半时光(当然不可能一直在死磕这道题),十年中每每学到一些新的知识都会进行一些尝试,但很多时候还是无功而返,大概在十天前复习数据结构相关知识的时候偶然发现了一个简单而且有趣的公式,然后灵感就来了,不过有一点点遗憾的是身为学数学的出身的,未能使用纯数学的方式解决,有一点点丢人,话不多说,请看正文。
102 0
关于哈密顿路是否存在的遍历算法