树的前中后序遍历

Recursion写法太简单,不值得一提。如果有人问你怎么写,那么他一定是要你写iterative的解法
这里是新版

preOrder Traversal的写法

public List preorderTraversal(TreeNode root) {
        Deque deque = new ArrayDeque<>();
        List ans = new ArrayList<>();
        if (root != null) deque.push(root);
        while (!deque.isEmpty()) {
            TreeNode node = deque.pop();
            ans.add(node.val);
            if (node.right != null) deque.push(node.right);
            if (node.left != null) deque.push(node.left);
        }
        return ans;
    }

Inorder traversal的建议写法:

 public List inorderTraversal(TreeNode root) {
        List ans = new ArrayList<>();
        Deque deque = new ArrayDeque<>();
        pushLeft(deque, root);
        while (!deque.isEmpty()) {
            TreeNode node = deque.pop();
            ans.add(node.val);
            pushLeft(deque, node.right);
        }
        return ans;
    }
    private void pushLeft(Deque deque, TreeNode node) {
        while (node != null) {
            deque.push(node);
            node = node.left;
        }
    }

preOrder Traversal的建议写法

public List postorderTraversal(TreeNode root) {
        Deque deque = new ArrayDeque<>();
        List ans = new ArrayList<>();
        TreeNode prev = null;
        pushLeft(deque, root);
        while (!deque.isEmpty()) {
            TreeNode node = deque.peek();
            if (node.right != null && prev != node.right) {
                pushLeft(deque, node.right);
            } else {
                ans.add(deque.pop().val);
                prev = node;
            }
        }
        return ans;
    }
    private void pushLeft(Deque deque, TreeNode node) {
        while (node != null) {
            deque.push(node);
            node = node.left;
        }
    }

下面是旧版

Preorder

先说preorder,这种最简单.
思路就是先把root丢进栈里。
每次从栈里pop一个元素出来,记下来元素的值,再把它的右孩子丢进去,再把左孩子丢进去。

 public List preorderTraversal(TreeNode root) {
        List ans = new ArrayList<>();
        Deque deque = new ArrayDeque<>();
        if (root == null) return ans;
        deque.push(root);
        while (!deque.isEmpty()) {
            TreeNode node = deque.pop();
            ans.add(node.val);
            if (node.right != null) deque.push(node.right);
            if (node.left != null) deque.push(node.left);
        }
        return ans;
    }

Inorder,

Lazy push做法

思路是先建一个空栈。然后借助一个helper变量, 初始化为root。
如果helper不是空的,把就helper丢进栈里,然后helper变成它的左孩子。如果helper是空的,表明已经走到最左边了。这时从栈里取一个元素pop出来,记下它的值,然后让helper等于它的右孩子。
每次从栈顶取元素时,要先把它的值记下来,再 try 它的右孩子,因为他的左孩子早已经 try过了。
这种做法我给它取了个名字叫做 lazy push, 被动压栈。

 public List inorderTraversal(TreeNode root) {
        Deque deque = new ArrayDeque();
        TreeNode helper = root;
        List result = new ArrayList<>();
        while(helper != null || !deque.isEmpty()) {
            if (helper != null) {
                deque.push(helper);
                helper = helper.left;
            } else {
                helper = deque.pop();
                result.add(helper.val);
                helper = helper.right;
            }
        }
        return result;
    }

Inorder: active push写法

第二种写法是积极压栈的写法。每拿到一个点,我就一路向左走到底,把它所有直系左孩子都放进栈里。
然后每次从栈顶pop取值,然后把pop出来这个点的右孩子的所有直系左孩子都放进去。
这个做法不需要像上次那样记录一个当前helper节点,感觉更好。
我把这种做法叫做active push, 积极压栈,以区分上面lazy push的写法。

    public List inorderTraversal(TreeNode root) {
        Deque deque = new LinkedList<>();
        List ans = new ArrayList<>();
        
        while (root != null) {
            deque.push(root);
            root = root.left;
        }
        while (!deque.isEmpty()) {
            TreeNode node = deque.pop();
            ans.add(node.val);
            node = node.right;
            while ( node != null) {
                deque.push(node);
                node = node.left;
            }
        }
        return ans;
    }

post order

积极压栈的写法

这种写法有点绕,我打赌你记不住,还是看上面的解法吧

    public List postorderTraversal(TreeNode root) {
        List result = new ArrayList();
        Deque stack = new LinkedList();
        TreeNode node = root;
        
        //push all the left node to the stack
        while(node != null) {
            stack.push(node);
            node = node.left;
        }
        //clearing all the stack
        while(!stack.isEmpty()) {
            node = stack.peek();
            if(node.right == null) { 
                result.add(node.val);
                stack.pop();
                while(!stack.isEmpty() && node == stack.peek().right) {
                    node = stack.pop();
                    result.add(node.val); 
                }
            }
            else {
                node = node.right;     
                while(node != null) {              
                    stack.push(node);
                    node = node.left;
                }
            }
        }
        return result;
    }

你可能感兴趣的:(树的前中后序遍历)