Morris算法

morris遍历算法可以将空间复杂度将为 O(1),从而实现时间复杂度为O(n),而空间复杂度为O(1)的遍历算法。

morris算法实现规则:

代码实现:

主函数类:

package Supplement;

import Tree.TreeNode;

public class MorrisMain {

    public static void main(String[] args){
        TreeNode root  = new TreeNode(1);
        TreeNode rootLeft = new TreeNode(2);
        TreeNode rootRight = new TreeNode(3);
        root.left= rootLeft;
        root.right = rootRight;

        TreeNode rootLeftLeft = new TreeNode(4);
        TreeNode rootLeftRight = new TreeNode(5);
        rootLeft.left = rootLeftLeft;
        rootLeft.right = rootLeftRight;

        TreeNode rootRightLeft = new TreeNode(6);
        TreeNode rootRightRight = new TreeNode(7);
        rootRight.left = rootRightLeft;
        rootRight.right = rootRightRight;

        //morris遍历
        MorrisPractice morrisPractice = new MorrisPractice();
        System.out.print("morris遍历: ");
    }
}

实现类:

package Supplement;

import Tree.TreeNode;

public class MorrisPractice {

    /**
     * morris遍历基础代码
     * 无需额外空间遍历
     * */
    public void morris(TreeNode head){
        if(head == null) return;;
        TreeNode cur = head;
        TreeNode 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){ //第一次来到这个结点
                    System.out.print(cur.value+" ");
                    mostRight.right = cur;
                    cur = cur.left;
                    continue;
                }else {
                    mostRight.right = null;
                    System.out.print(cur.value+" ");
                }
            }else{
                System.out.print(cur.value+" ");
            }
            cur = cur.right;
        }
        System.out.println();
    }
}

代码运行过程:

morris算法实现先序遍历:在第一次经过节点和无左节点时打印

//morris - 先序遍历
    public void morrisPre(TreeNode head){
        if(head == null) return;
        TreeNode cur = head;
        TreeNode 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){ //第一次结点
                    System.out.print(cur.value+" ");
                    mostRight.right = cur;
                    cur = cur.left;
                    continue;
                }else { //第二次
                    mostRight.right = null;
                }
            }else { //无左节点 -- 叶子结点
                System.out.print(cur.value+" ");
            }
            cur = cur.right;
        }
        System.out.println();
    }

中序遍历:

//morris - 中序遍历
    public void morrisIn(TreeNode head){
        if(head == null) return;
        TreeNode cur = head;
        TreeNode 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 morrisPos(TreeNode head){
        if(head == null) return;
        TreeNode cur = head;
        TreeNode 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;
                    printRightNode(cur.left);
                }
            }
            cur = cur.right;
        }
        printRightNode(head); //打印最后的根节点的右边界
    }
    //逆向打印树的右边界(树的所有右节点)
    public void printRightNode(TreeNode node){
        if(node == null) return;
        TreeNode cur = reverseNode(node); //逆转结点
        TreeNode tmp = cur;
        while (tmp != null){
            System.out.print(tmp.value+" ");
            tmp = tmp.right;
        }
        reverseNode(cur); //恢复结点
    }
    //反转结点指向(类反转链表
    public TreeNode reverseNode(TreeNode node){
        TreeNode  next = null;
        TreeNode cur = null;
        while (node != null){
            next = node.right;
            node.right = cur;
            cur = node;
            node = next;
        }
        return cur;
    }
posted @ 2022-03-06 15:27  彬哙  阅读(227)  评论(0)    收藏  举报