1. 程式人生 > 其它 >遍歷二叉樹的統一寫法

遍歷二叉樹的統一寫法

通過前面的實踐我們知道前序和後序遍歷二叉樹的迭代寫法可以用同一個寫法,但是到了中序遍歷二叉樹的時候,由於遍歷結點和處理結點不能同時進行,就導致我們需要重新構思思路,非常難用,那麼前中後序迭代法遍歷二叉樹能不能像它們的遞迴寫法一樣,有一個統一寫法呢?答案是肯定,直接上程式碼:

中序:

//前中後序遍歷統一寫法,用空指標標記已訪問的結點。
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