Morris 遍历的是指就是避免用栈结构,而是让下层到上层有指针,具体时通过让底层节点指向 null 的空闲指针指回上层的某个节点,从而完成下层到上层的移动。
Morris 遍历的过程:
假设当前节点为cur,初始时cur就是整棵树的头节点,根据以下标准让cur移动:
1. 如果 cur 为 null,则过程停止,否则继续下面的过程。
2. 如果 cur 没有左子树,则让cur向右移动,即令 cur = cur.right。
3. 如果 cur 有左子树,则找到cur左子树上最右的节点,记为 mostRight。
1)如果 mostRight 的right指针指向null,则令 mostRight.right = cur,也就是让mostRight 的right指针指向当前节点,然后让cur向左移动,即令 cur = cur.left。
2)如果 mostRight 的right指针指向cur,则令 mostRight.right = null,也就是让 mostRight的right指针指向null,然后让cur向右移动,即令cur = cur.right。
举例:

 
 
 
Morris 序代码实现:
    public static void morris(Node head) {
        if (head == null) {
            return;
        }
        Node cur = head;
        Node mostRight = null;
        while (cur != null) {
            mostRight = cur.left;
            //如果当前cur有左子树
            if (mostRight != null) {
                //找到左子树上最右的节点
                while (mostRight.right != null && mostRight.right != cur) {
                    mostRight = mostRight.right;
                }
                //上面的while结束后,mostRight就是最右的节点
                if (mostRight.right == null) {
                    mostRight.right = cur;
                    cur = cur.left;
                    continue;//回到最外层的while,继续判断cur的情况
                } else {
                    //如果mostRight指向cur 让其指回null
                    mostRight.right = null;
                }
            } 
            //cur如果没有左子树,cur向右移动
            //或者cur左子树的最右节点的右指针是指向cur的,cur向右移动
            cur = cur.right;
        }
    }根据 Morris 遍历,加工出先序遍历:
1. 对于cur只能到达一次的节点(无左子树的节点),cur到达时直接打印
2. 对于cur可以到达两次的节点(有左子树的节点),cur第一次到达时打印,第二次到达时不打印。
先序遍历:
    public static 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节点
                while (mostRight.right != null && mostRight.right != cur) {
                    mostRight = mostRight.right;
                }
                //当mostRight 为空时,说明第一次到达这个节点 直接打印。
                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;
        }
    }根据 Morris 遍历,加工出中序遍历:
1. 对于cur只能到达一次的节点(无左子树的节点),cur到达时直接打印
2. 对于cur可以到达两次的节点(有左子树的节点),cur第一次到达时不打印,第二次到达时打印。
中序遍历:
    public static void morrisIn(Node head) {
        if (head == null) {
            return;
        }
        Node cur = head;
        Node mostRight = null;
        while (cur != null) {
            mostRight = cur.left;
            //这里是有左子树的情况
            if (mostRight != null) {
                //这个while循环就是找 mostRight节点
                while (mostRight.right != null && mostRight.right != cur) {
                    mostRight = mostRight.right;
                }
                //当mostRight 为空时,说明第一次到达这个节点 中序中不打印。
                if (mostRight.right == null) {
                    mostRight.right = cur;
                    cur = cur.left;
                    continue;
                    //这里说明第二次到达这个节点 在中序中此处需要打印
                } else {
                    System.out.print(cur.value + " ");
                    mostRight.right = null;
                }
                //这里就是没有左子树的情况 直接打印
            } else {
                System.out.print(cur.value + " ");
            }
            cur = cur.right;
        }
    }测试结果:
        Node head = new Node(1);
        Node node1 = new Node(2);
        Node node2 = new Node(3);
        Node node3 = new Node(4);
        Node node4 = new Node(5);
        Node node5 = new Node(6);
        head.left = node1;
        head.right = node2;
        node1.left = node3;
        node1.right = node4;
        node2.right = node5;
        morrisPre(head);
        System.out.println();
        morrisIn(head);



















