1. 程式人生 > 其它 >二叉樹——線索化遍歷

二叉樹——線索化遍歷

1. Morris遍歷

1.1. 思路

Morris遍歷通過利用左子樹前序遍歷下的最後一個節點的right指標,來做到以時間複雜度為O(n)空間複雜度為O(1)的開銷遍歷一個二叉樹。

1.2. 程式碼

    public static <T> void morrisPre(TreeNode<T> root, Consumer<T> consumer) {
        TreeNode<T> cur = root;
        while (cur != null) {
            if (cur.left != null) {
                TreeNode<T> leftLast = cur.left;
                while (leftLast.right != null && leftLast.right != cur)
                    leftLast = leftLast.right;
                if (leftLast.right == null) {
                    leftLast.right = cur;
                } else {
                    leftLast.right = null;
                    cur = cur.right;
                    continue;
                }
            }
            consumer.accept(cur.val);
            cur = cur.left != null ? cur.left : cur.right;
        }
    }

    public static <T> void morrisMid(TreeNode<T> root, Consumer<T> consumer) {
        TreeNode<T> cur = root;
        while (cur != null) {
            if (cur.left != null) {
                TreeNode<T> leftLast = cur.left;
                while (leftLast.right != null && leftLast.right != cur) {
                    leftLast = leftLast.right;
                }
                if (leftLast.right == null) {
                    leftLast.right = cur;
                    cur = cur.left;
                    continue;
                } else {
                    leftLast.right = null;
                }
            }
            consumer.accept(cur.val);
            cur = cur.right;
        }
    }

    public static <T> void morrisPost(TreeNode<T> root, Consumer<T> consumer) {
        TreeNode<T> cur = root;
        while (cur != null) {
            if (cur.left != null) {
                TreeNode<T> leftLast = cur.left;
                while (leftLast.right != null && leftLast.right != cur) {
                    leftLast = leftLast.right;
                }
                if (leftLast.right == null) {
                    leftLast.right = cur;
                } else {
                    leftLast.right = null;
                    consumeRightBound(cur.left, consumer);
                    cur = cur.right;
                    continue;
                }
            }
            cur = cur.left != null ? cur.left : cur.right;
        }
        consumeRightBound(root, consumer);
    }

    private static <T> void consumeRightBound(TreeNode<T> node, Consumer<T> consumer) {
        TreeNode<T> pre = null;
        TreeNode<T> cur = node;
        TreeNode<T> next;
        while (cur != null) {
            next = cur.right;
            cur.right = pre;
            pre = cur;
            cur = next;
        }
        cur = pre;
        pre = null;
        while (cur != null) {
            consumer.accept(cur.val);
            next = cur.right;
            cur.right = pre;
            pre = cur;
            cur = next;
        }
    }