二叉树遍历Java版(前中后序的递归,迭代,Morris以及两种特殊的先序遍历)

二叉树的遍历

先序

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    static List<Integer> res;

    public List<Integer> preorderTraversal(TreeNode root) {
        res = new ArrayList<>();
        // preorderRecursion(root);
        // preorder(root);
        // preorderMorris(root);
//        return res;
        preorder3(root);
        Collections.reverse(res);
        return res;
    }

    // 假先序
    public static void preorder3(TreeNode root) {
        if (root == null) return;
        preorder3(root.right);
        preorder3(root.left);
        res.add(root.val);
    }
    
    // 保存右节点
    public static void perorder2(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
            res.add(cur.val);
            if (cur.right != null) stack.push(cur.right);
            if (cur.left != null) stack.push(cur.left);
        }
    }
    
    // Morris
    public static void preorderMorris(TreeNode root) {
        if (root == null) return;

        TreeNode cur = root;

        while (cur != null) {
            if (cur.left != null) {
                // 左子树不空,遍历左子树,找到左子树的最右侧节点
                TreeNode rightMost = cur.left;
                while (rightMost.right != null && rightMost.right != cur) {
                    rightMost = rightMost.right;
                }
                // 最右侧节点的右指针指向null或者cur
                if (rightMost.right == null) {
                    // 有左右孩子的节点第一次被访问
                    res.add(cur.val);
                    // 把最右侧节点的right指向cur
                    rightMost.right = cur;
                    // 访问左子树
                    cur = cur.left;
                } else {
                    // 有左右孩子的节点第二次被访问
                    // 恢复
                    rightMost.right = null;
                    // 遍历右子树
                    cur = cur.right;
                }
            } else {
                // 只有右孩子的节点只会被访问一次
                res.add(cur.val);
                // 遍历右子树
                cur = cur.right;
            }
        }
    }

    // 非递归
    public static void preorder(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        while (!stack.isEmpty() || root != null) {
            while (root != null) {
                res.add(root.val);
                stack.add(root);
                root = root.left;
            }
            root = stack.pop();
            root = root.right;
        }
    }

    // 递归
    public static void preorderRecursion(TreeNode root) {
        if (root == null)
            return;
        res.add(root.val);
        preorderRecursion(root.left);
        preorderRecursion(root.right);
    }
}

中序

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    static List<Integer> res;

    public List<Integer> inorderTraversal(TreeNode root) {
        res = new ArrayList<>();
//        inorderRecursion(root);
//        inorder(root);
        inorderMorris(root);
        return res;
    }

    public static void inorderMorris(TreeNode root) {
        if (root == null) return;
        TreeNode cur = root;
        while (cur != null) {
            if (cur.left != null) {
                TreeNode rightMost = cur.left;
                while (rightMost.right != null && rightMost.right != cur) {
                    rightMost = rightMost.right;
                }
                if (rightMost.right == null) {
                    rightMost.right = cur;
                    cur = cur.left;
                } else {
                    // 有左右孩子的节点第二次被经过,左子树都遍历完了,访问节点
                    res.add(cur.val);
                    rightMost.right = null;
                    cur = cur.right;
                }
            } else {
                // 只有右孩子的节点只会被经过一次,直接访问
                res.add(cur.val);
                cur = cur.right;
            }
        }
    }

    public static void inorder(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> stack = new Stack<>();
        while (!stack.isEmpty() || root != null) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            res.add(root.val);
            root = root.right;
        }
    }

    public static void inorderRecursion(TreeNode root) {
        if (root == null) return;
        inorderRecursion(root.left);
        res.add(root.val);
        inorderRecursion(root.right);
    }
}

后序

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
public class Solution {
    static List<Integer> res;

    public List<Integer> postorderTraversal(TreeNode root) {
        res = new ArrayList<>();
//        postorderRecursion(root);
//        postorder(root);
        postorderMorris(root);
        return res;
    }

    public static void postorderMorris(TreeNode root) {
        TreeNode cur = root;
        while (cur != null) {
            if (cur.left != null) {
                TreeNode rightMost = cur.left;
                while (rightMost.right != null && rightMost.right != cur) {
                    rightMost = rightMost.right;
                }
                if (rightMost.right == null) {
                    rightMost.right = cur;
                    cur = cur.left;
                } else {
                    rightMost.right = null;
                    // 一个节点被第二次经过的时候,自底向上访问左子树的所有的右节点
                    visitReversedRightTree(cur.left);
                    cur = cur.right;
                }
            } else {
                cur = cur.right;
            }
        }
        // 再遍历一次
        visitReversedRightTree(root);
    }

    // 自底向上访问右节点(访问反转后的右节点)
    public static void visitReversedRightTree(TreeNode root) {
        // 反转右子树
        TreeNode reversed = reverseRightTree(root);
        TreeNode cur = reversed;
        while (cur != null) {
            res.add(cur.val);
            cur = cur.right;
        }
        // 反转回去
        reverseRightTree(reversed);
    }

    // 把右子树反转
    public static TreeNode reverseRightTree(TreeNode root) {
        TreeNode pre = null;
        TreeNode cur = root;
        while (cur != null) {
            TreeNode nextRight = cur.right;
            cur.right = pre;
            pre = cur;
            cur = nextRight;
        }
        return pre;
    }

    public static void postorder(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pre = null;
        while (!stack.isEmpty() || root != null) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }

            root = stack.pop();
            if (root.right == null || root.right == pre) {
                // 没有右子树或者右子树已经被访问过了
                res.add(root.val);
                // pre始终指向上一个被访问过的节点
                pre = root;
                root = null;
            } else {
                // 访问右子树前,先把当前节点重新入栈
                stack.push(root);
                root = root.right;
            }
        }
    }

    public static void postorderRecursion(TreeNode root) {
        if (root == null) return;
        postorderRecursion(root.left);
        postorderRecursion(root.right);
        res.add(root.val);
    }
}
posted @ 2022-06-08 18:02  n1ce2cv  阅读(28)  评论(0编辑  收藏  举报