Binary tree Maurice (Morris) traversal

What is traversed Morris

In fact, the complexity of optimizing space to O (1) of the binary tree traversal algorithm.

For general traversal algorithm, we are using the node needs to store the stack after the visit again. Worst case, we need to store the entire binary tree node. Therefore, the space complexity is O (n). Morris sucked while traversing space complexity down to O (1) level. Morris used to traverse the concept of "clues binary tree", in fact, is the use of a null pointer around the leaf node to store some kind of predecessor nodes or traverse the successor node. So there is no additional space.

Morris thought traversal algorithm

Suppose the current node is a cur, and assigned to root root at the start.

  1. Determining whether the node is empty cur
  2. If not empty
    1) If no left child cur, cur update right, namely (cur = cur.right)
    2) If there is cur left child, the child is left to the far right of the tree to find the node pre
    • If the right child of pre empty, then the right child pointing cur. pre.right = cur
    • If the child is right pre cur, then it is pointing to empty. pre.right = null. (Reducing the tree structure)
  3. cur is empty, stop the walk

Pre-order traversal Morris

Take the following as an example of a simple binary tree, briefly explain Morris before traversing process.
Here Insert Picture Description

  • The root node 1 is set to cur.
  • Because the left child node cur (node ​​1) is not empty, and cur (Node 1) 2 is not empty, so we find left sub-tree root node to node 2 as the rightmost node 5.
  • 5 right child node is empty, then we CUR value output (node ​​1), and the right child node pointed to 5 cur, i.e. a node. Update cur cur left child node, that node 2.
  • Because cur (Node 2) the child is not left empty, finds its left subtree rightmost node 4
  • 4 right child node is empty, the first output value cur (Node 2), and then the right child node 4 points cur (Node 2), and update the cur (Node 2) to its left child node 4.
  • This time cur (node ​​4) the child is left empty, so the right to access their child, the child found the right point to the node 2, so we will update the cur node 2.
  • This time we find that cur in turn points to the node 2, the left child node 4 is not empty, we find left subtree rightmost node 4 again, but this time the node right child 4 points to the cur, so we delete it, That points to right child node 4 is empty, restore the original tree structure. And because children have visited and left the root node, so this time we visit its right child node 5.
public void Morris_preorderTraversal(TreeNode root){
    TreeNode cur = root;
    while(cur!=null){
        if(cur.left!=null){
            TreeNode pre = cur.left;
            while(pre.right!=null && pre.right!=cur){
                pre = pre.right;
            }
            if(pre.right == null){	// 第一次到达左子树的最右端
                System.out.print(cur.val);
                pre.right = cur;
                cur = cur.left;
            }
            else{ // 第二次到达左子树的最右端
                pre.right = null;
                cur = cur.right;
            }
        }
        else{
            System.out.print(cur.val);
            cur = cur.right;
        }
    }
}

Morris preorder

Morris and traversal sequence preorder traversal or less, the output appears a change in position.

public void Morris_inorderTraversal(TreeNode root){
        TreeNode cur = root;
        while(cur!=null){
            if(cur.left!=null){
                TreeNode pre = cur.left;
                while(pre.right!=null && pre.right!=cur){
                    pre = pre.right;
                }
                if(pre.right == null){
                    pre.right = cur;
                    cur = cur.left;
                }
                else{
                    pre.right = null;
                    System.out.print(cur.val);
                    cur = cur.right;
                }
            }
            else {
                System.out.print(cur.val);
                cur = cur.right;
            }
        }
    }

After Morris-order traversal

Morris postorder This is among the most complex. Because children need the right output before the root node. For the FIG., When the postorder traversal order: 4,5,2,6,3,1. We can see to the left sub-tree node 1, nodes 2 and 5 is the right boundary, as long as we reverse output, access order after order traversal can be achieved. Therefore, we need a function to be reversed, that node 5 points to node 2. And after the output, which is then reversed back (without changing the structure of the tree).
Here Insert Picture Description

public TreeNode reverseNode(TreeNode node){
    TreeNode pre = null;
    TreeNode next = null;
    while(node!=null){
        next = node.right;
        node.right = pre;
        pre = node;
        node = next;
    }
    return pre;
}

public void printNode(TreeNode node){
    TreeNode tail = reverseNode(node);
    TreeNode cur = tail;
    while(cur!=null){
        System.out.println(cur.val);
        cur = cur.right;
    }
    reverseNode(tail);
}

public void Morris_postorderTraversal(TreeNode root) {
    TreeNode cur = root;
    while(cur != null){
        if(cur.left!=null){
            TreeNode pre = cur.left;
            while(pre.right!=null && pre.right!=cur){
                pre = pre.right;
            }
            if(pre.right==null){
                pre.right = cur;
                cur = cur.left;
            }
            else{
                pre.right = null;
                printNode(cur.left);
                cur = cur.right;
            }
        }
        else{
            cur = cur.right;
        }
    }
    printNode(root);
}

to sum up

Morris traversing the binary tree traversal of space complexity down to O (1), of course, still time complexity is O (n).

Released five original articles · won praise 0 · Views 100

Guess you like

Origin blog.csdn.net/danmo_wuhen/article/details/104339630