Morris遍歷


Morris遍歷時間復雜度為O(n),空間復雜度為O(1)。可以通過Morris遍歷完成先序中序后續遍歷。

在Morris遍歷中,若當前節點有左孩子,則會訪問該節點兩次。若無左孩子,則會訪問該節點一次。至於遍歷順序與遞歸遍歷類似。遍歷順序由在第幾次訪問該節點時輸出決定。

對於有左孩子的節點,第一次訪問到便輸出,為先序遍歷。第二次訪問時輸出為中序遍歷

后序遍歷為:第二次訪問到某一節點是,逆序的打印其左子樹的最右邊界。最后單獨逆序打印整棵樹的右邊界。

Morris遍歷規則:

1.對於當前節點cur,若cur無左孩子,則cur=cur.right。

2.如果cur有左孩子,找到cur左子樹最右節點,記為mostright。

  2.1如果mostright右孩子為空,則mostright.right=cur。cur向左移動。(此時為第一次訪問該節點)

  2.2如果mostright右孩子為cur,則mostright.right=null。cur向右移動(此時為第二次訪問該節點)


對於以下二叉樹:

 

 訪問順序為:1  2  4  2   5  1  3  6  3  7

 

先序遍歷順序:1 2 4 5 3 6 7(所有節點均第一次訪問時輸出)

中序遍歷順序:4 2 5 1 3 6 7(有左孩子的節點第二次訪問時輸出)

后序遍歷順序:4 5 2 6 7 3 1(有左孩子的節點第二次訪問時,逆序輸出左子樹的右邊界,最后加上整棵樹的逆序右邊界。對於2,輸出4,對於1輸出5,2 對於3,輸出6,最后輸出7 3 1)

先序遍歷:

package Leetcode;

public class Morris {
    public void preOrder(TreeNode head){
        if(head==null){
            return;
        }
        TreeNode cur =head;
        TreeNode mostRight ;
        while (cur!=null){
            if(cur.left==null){
                System.out.println(cur.val);
                cur = cur.right;
            }else{
                mostRight = cur.left;
                //尋找左子樹最右節點
                while (mostRight.right!=null&&mostRight.right!=cur){
                    mostRight = mostRight.right;
                }
                if(mostRight.right==null){
                    //此時為第一次訪問該節點
 System.out.println(cur.val);
                    mostRight.right = cur;
                    cur = cur.left;
                }else{
                    //此時為第二次訪問該節點
                    mostRight.right=null;
                    cur = cur.right;
                }
            }
        }
    }

}

中序遍歷:

package Leetcode;

public class Morris {
    public void inOrder(TreeNode head){
        if(head==null){
            return;
        }
        TreeNode cur =head;
        TreeNode mostRight ;
        while (cur!=null){
            if(cur.left==null){
                System.out.println(cur.val);
                cur = cur.right;
            }else{
                mostRight = cur.left;
                //尋找左子樹最右節點
                while (mostRight.right!=null&&mostRight.right!=cur){
                    mostRight = mostRight.right;
                }
                if(mostRight.right==null){
                    //此時為第一次訪問該節點
                    mostRight.right = cur;
                    cur = cur.left;
                }else{
                    //此時為第二次訪問該節點
 System.out.println(cur.val);
                    mostRight.right=null;
                    cur = cur.right;
                }
            }
        }
    }

    public static void main(String[] args) {
        Morris m =new Morris();
        TreeNode t1 = new TreeNode(1);
        TreeNode t2 = new TreeNode(2);
        TreeNode t3 = new TreeNode(3);
        TreeNode t4 = new TreeNode(4);
        TreeNode t5 = new TreeNode(5);
        TreeNode t6 = new TreeNode(6);
        TreeNode t7 = new TreeNode(7);
        t1.left = t2;
        t1.right = t3;
        t2.left= t4;
        t2.right= t5;
        t3.left= t6;
        t3.right= t7;

        m.preOrder(t1);
    }
}

后序遍歷:

package Leetcode;

import java.util.Stack;

public class Morris {
    public void postOrder(TreeNode head){
        if(head==null){
            return;
        }
        TreeNode cur =head;
        TreeNode mostRight ;
        while (cur!=null){
            if(cur.left==null){
                cur = cur.right;
            }else{
                mostRight = cur.left;
                //尋找左子樹最右節點
                while (mostRight.right!=null&&mostRight.right!=cur){
                    mostRight = mostRight.right;
                }
                if(mostRight.right==null){
                    //此時為第一次訪問該節點
                    mostRight.right = cur;
                    cur = cur.left;
                }else{
                    //此時為第二次訪問該節點
                    mostRight.right=null;
                    sout(cur.left);
                    cur = cur.right;
                }
            }
        }
        sout(head);
    }
    //逆序輸出當前節點左子樹的右邊界
    private void sout(TreeNode node) {
        Stack<Integer> stack = new Stack<>();
        while (node!=null){
            stack.add(node.val);
            node = node.right;
        }
        while (!stack.isEmpty()){
            System.out.println(stack.pop());
        }
    }

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM