morris Traversal

O(n)时间,O(1)空间对二叉树进行前序、中序、后序遍历。详细讲解看参考。

public class Solution {

    public static void morrisPreorder(TreeNode root) {
        TreeNode cur = root;
        TreeNode pre = null;

        while (cur != null) {
            if (cur.left == null) {
                System.out.print(cur.val + " ");
                cur = cur.right;
            } else {
                // find predecessor
                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;
                }

            }

        }
        System.out.println();

    }

    public static void morrisInorder(TreeNode root) {
        TreeNode cur = root;
        TreeNode pre = null;

        while (cur != null) {
            if (cur.left == null) {
                System.out.print(cur.val + " ");
                cur = cur.right;
            } else {
                // find predecessor
                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;
                }

            }

        }

        System.out.println();
    }

    public static void morrisPostorder(TreeNode root) {
        TreeNode dump = new TreeNode(0);
        dump.left = root;
        TreeNode cur = dump;
        TreeNode pre = null;

        while (cur != null) {
            if (cur.left == null) {
                cur = cur.right;
            } else {
                // find predecessor
                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;
                    printRev(cur.left, pre);
                    cur = cur.right;
                }

            }
        }
        System.out.println();

    }

    private static void printRev(TreeNode from, TreeNode to) {
        reverse(from, to);

        TreeNode p = to;
        while (true) {
            System.out.print(p.val + " ");
            if (p == from)
                break;
            p = p.right;
        }
        reverse(to, from);
    }

    private static void reverse(TreeNode from, TreeNode to) {
        if (from == to)
            return;
        TreeNode pre = from, cur = from.right, post = null;
        while (pre != to) {
            post = cur.right;
            cur.right = pre;
            pre = cur;
            cur = post;
        }

    }

    public static void main(String[] args) {
        String s = "6 2 1 # # 4 3 # # 5 # # 7 # 9 # 8 # #";
        TreeNode root = TreeUtils.makeTree(s);
        TreeUtils.printTree(root);
        morrisPreorder(root);
        morrisInorder(root);
        morrisPostorder(root);

    }

}

复杂度分析:

空间复杂度:O(1),因为只用了两个辅助指针。

时间复杂度:O(n)。证明时间复杂度为O(n),最大的疑惑在于寻找中序遍历下二叉树中所有节点的前驱节点的时间复杂度是多少,即以下两行代码:

while (pre.right != null && pre.right != cur)
    pre = pre.right;

直觉上,认为它的复杂度是O(nlgn),因为找单个节点的前驱节点与树的高度有关。但事实上,寻找所有节点的前驱节点只需要O(n)时间。n个节点的二叉树中一共有n-1条边,整个过程中每条边最多只走2次,一次是为了定位到某个节点,另一次是为了寻找上面某个节点的前驱节点,如下图所示,其中红色是为了定位到某个节点,黑色线是为了找到前驱节点。所以复杂度为O(n)。

参考(讲的太好了):

http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html

时间: 2024-11-03 01:30:55

morris Traversal的相关文章

C前序遍历二叉树Morris Traversal算法

首先来递归算法,简单易懂: #include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef struct TreeNode{ char data; struct TreeNode *lchild, *rchild; }TreeNode; void PreOrderTraverse(TreeNode *t){ if( NULL == t ) return; printf("%c",

Morris Traversal方法遍历

实现二叉树的遍历且只需要O(1)的空间. 参考:http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html

Morris Traversal: 非递归不用栈实现对树的中序遍历

参考:http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/ <pre name="code" class="plain">1. Initialize current as root 2. While current is not NULL If current does not have left child a) Print cu

Binary Tree Inorder Traversal [leetcode] 非递归的三种解法

第一种方法是Morris Traversal 是O(n)时间复杂度,且不需要额外空间的方法.缺点是需要修改树. 通过将叶子节点的right指向其中序后继. 代码如下 vector<int> inorderTraversal(TreeNode *root) { vector<int> res; TreeNode * cur = root; TreeNode * pre = NULL; while (cur) { if (cur->left == NULL) { res.push

【转载】Morris遍历二叉树 &amp; BST(二叉搜索树) Traverse &amp; 空间O(1) 时间O(n)

因为做一道Leetcode的题目(前面博客有:link),需要用Space O(1)空间复杂度来中序遍历树, 看了Discuss,也上网搜了一下,发现空间O(1)可以用 Morris遍历的方法.方法介绍如下: http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html其中,中序遍历和前序遍历比较方便解决: 通常,实现二叉树的前序(preorder).中序(inorder).后序(postorder)遍历有两个常用

Binary Tree Traversal

1. Preorder Tree Traversal 1 // Solution 1. With Stack 2 // Time Complexity : O(n) 3 // Space Complexity: O(h) ~ O(log n) 4 public class Solution { 5 public List<Integer> preorderTraversal(TreeNode root) { 6 ArrayList<Integer> list = new Array

37. Binary Tree Zigzag Level Order Traversal &amp;&amp; Binary Tree Inorder Traversal

Binary Tree Zigzag Level Order Traversal Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). For example: Given binary tree {3,9,20,

Morris 遍历二叉树

Morris Traversal 方法实现前序.中序以及后序遍历二叉树.相比使用栈或者递归(也是通过栈空间)方法,Morris 方法可以在空间复杂度为 O(1),时间复杂度为 O(n) 的条件下实现对二叉树的遍历. 前序遍历 如果当前节点左孩子 cur->left 为空,输出当前节点 cur 并指向右孩子 cur->right. 如果当前节点左孩子 cur->left 不为空,那么在当前节点的左子树中找出前驱节点 pre,也就是左子树中最大的点. 如果前驱节点的右孩子 pre->r

99. Recover Binary Search Tree

two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing its structure. Note:A solution using O(n) space is pretty straight forward. Could you devise a constant space solution? 解题思路:本题主要是考查了Morris Traversal