二叉树——线索化遍历

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;
        }
    }
posted @ 2022-05-10 18:14  迈吉  阅读(20)  评论(0编辑  收藏  举报