遍历二叉树的统一写法

通过前面的实践我们知道前序和后序遍历二叉树的迭代写法可以用同一个写法,但是到了中序遍历二叉树的时候,由于遍历结点和处理结点不能同时进行,就导致我们需要重新构思思路,非常难用,那么前中后序迭代法遍历二叉树能不能像它们的递归写法一样,有一个统一写法呢?答案是肯定,直接上代码:

中序:

//前中后序遍历统一写法,用空指针标记已访问的结点。
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Deque<TreeNode> stack = new LinkedList<>();
        if (root != null) stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
            if (cur != null) {
                //右中左 出栈就是左中右中序遍历
                if (cur.right != null) stack.push(cur.right);
                //用空指针标记已遍历未处理的结点
                stack.push(cur);
                stack.push(null);
                if (cur.left != null) stack.push(cur.left);
            } else {
                //处理结点
                cur = stack.pop();
                res.add(cur.val);
            }
        }
        return res;
    }
}

先序:

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Deque<TreeNode> stack = new LinkedList<>();
        if (root != null) stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
            if (cur != null) {
                //先放入右结点,再放入左结点,出栈就是先左后右
                if (cur.right != null) stack.push(cur.right);
                if (cur.left != null) stack.push(cur.left);
                //遍历中结点,空指针标记未处理
                stack.push(cur);
                stack.push(null);
            } else {
                //处理结点
                cur = stack.pop();
                res.add(cur.val);
            }
        }
        return res;
    }
}

后序:

 class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Deque<TreeNode> stack = new LinkedList<>();
        if (root != null) stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
            if (cur != null) {
                //空指针标记已遍历未处理
                stack.push(cur);
                stack.push(null);
                if (cur.right != null) stack.push(cur.right);
                if (cur.left != null) stack.push(cur.left);
            } else {
                //处理结点
                cur = stack.pop();
                res.add(cur.val);
            }
        }
        return res;
    }
}

总结:先遍历,后处理,用空指针标记已遍历未处理的结点。妙!

参考:programmercarl.com

posted @ 2022-03-27 16:03  一梦两三年13  阅读(44)  评论(0)    收藏  举报