Morris Traversal -Preorder & Inorder & Postorder

java version

import java.util.ArrayList;

public class Learn {
    
    
    public static void main(String[] args) {
    
    
        TreeNode root = new TreeNode(5);
        root.left = new TreeNode(2);
        root.left.left = new TreeNode(1);
        root.left.right = new TreeNode(4);
        root.left.right.left = new TreeNode(3);
        root.right = new TreeNode(6);
        root.right.right = new TreeNode(7);
        BinaryTree tree = new BinaryTree(root);
        tree.postOrderMorris(tree.root);
        for(int a : tree.postorder) System.out.println(a);
    }
}

class TreeNode {
    
    
    int val;
    TreeNode left, right;

    public TreeNode(int x) {
    
    
        val = x;
        left = right = null;
    }
}

class BinaryTree {
    
    
    TreeNode root;
    ArrayList<Integer> preorder, inorder, postorder;

    public BinaryTree(TreeNode root) {
    
    
        this.root = root;
        preorder = new ArrayList<>();
        inorder = new ArrayList<>();
        postorder = new ArrayList<>();
    }

    //Recursion
    //Time: O(n)
    //Space: O(n)

    public void preOrderRecursion(TreeNode root) {
    
    
        if(root == null) return;
        preorder.add(root.val);
        preOrderRecursion(root.left);
        preOrderRecursion(root.right);
        return;
    }

    public void inOrderRecursion(TreeNode root) {
    
    
        if(root == null) return;
        inOrderRecursion(root.left);
        inorder.add(root.val);
        inOrderRecursion(root.right);
        return;
    }

    public void postOrderRecursion(TreeNode root) {
    
    
        if(root == null) return;
        postOrderRecursion(root.left);
        postOrderRecursion(root.right);
        postorder.add(root.val);
        return;
    }

    //Morris Traversal
    //Time: O(n)
    //Space: O(1)

    public void preOrderMorris(TreeNode root) {
    
    
        while(root != null) {
    
    
            if(root.left != null) {
    
    
                //if has left subtree
                TreeNode lmr = getLeftMostRight(root);
                if(lmr.right == root) {
    
    
                    //currently at root, and its left has been traversed
                    //return from this link
                    lmr.right = null;  //remove link
                    // preorder.add(root.val);
                    root = root.right;
                } else {
    
    
                    //make link
                    lmr.right = root;
                    preorder.add(root.val);
                    root = root.left;
                }
            } else {
    
    
                //if left subtree is empty
                preorder.add(root.val);
                root = root.right;
            }
        }
        return;
    }

    public void inOrderMorris(TreeNode root) {
    
    
        while(root != null) {
    
    
            if(root.left != null) {
    
    
                //if has left subtree
                TreeNode lmr = getLeftMostRight(root);
                if(lmr.right == root) {
    
    
                    //currently at root, and its left has been traversed
                    //return from this link
                    lmr.right = null;  //remove link
                    inorder.add(root.val);
                    root = root.right;
                } else {
    
    
                    //make link
                    lmr.right = root;
                    root = root.left;
                }
            } else {
    
    
                //if left subtree is empty
                inorder.add(root.val);
                root = root.right;
            }
        }
        return;
    }

    //visit only occurs when goes down right
    //向右下方斜着一条一条访问
    public void postOrderMorris(TreeNode root) {
    
    
        TreeNode node = root;
        while(node != null) {
    
    
            if(node.left != null) {
    
    
                //if has left subtree
                TreeNode lmr = getLeftMostRight(node);
                if(lmr.right == node) {
    
    
                    //currently at node, and its left has been traversed
                    //return from this link
                    lmr.right = null;  //this link only serves for go back, till this point, its mission is completed
                    visitReversedEdgeDownRight(node.left);
                    node = node.right;
                } else {
    
    
                    //make link
                    lmr.right = node;
                    node = node.left;
                }
            } else {
    
    
                //if left subtree is empty
                node = node.right;
            }
        }
        visitReversedEdgeDownRight(root);  //最后一条右下斜访问,因为每次访问都从左子过来,root没有父节点能过来,所以单独拉出来
        return;
    }

    //only reverse the edge which goes down right
    //return the tail node in the original tree
    public TreeNode reverseRight(TreeNode root) {
    
    
        TreeNode prev = root, cur = root.right;
        prev.right = null;
        while(cur != null) {
    
    
            TreeNode temp = cur.right;
            cur.right = prev;
            prev = cur;
            cur = temp;
        }
        return prev;
    }

    public void visitReversedEdgeDownRight(TreeNode root) {
    
    
        // if(root == null) return;
        TreeNode tail = reverseRight(root);
        TreeNode node = tail;
        while(node != null) {
    
    
            postorder.add(node.val);
            node = node.right;
        }
        reverseRight(tail);  //recover the original right edge
        return;
    }

    //requires that root has left tree, root.left is not null
    public TreeNode getLeftMostRight(TreeNode root) {
    
    
        TreeNode node = root.left;
        while(node.right != null && node.right != root) node = node.right;
        return node;
    }
}

猜你喜欢

转载自blog.csdn.net/sinat_37517996/article/details/114150247