二叉树——前序、中序、后序遍历(递归+迭代)

给你二叉树的根节点 root ,返回它节点值的 前序、中序、后序 遍历。

二叉树——前序、中序、后序遍历(递归+迭代)_第1张图片

对应的中序、后序结果分别为 [1,3,2] 和 [3,2,1]

解题方法:①递归法、②各自为营的迭代法(每种都有自己的特点,不具有模板性)、③模板迭代

①递归法

前序:

class Solution {
    public List preorderTraversal(TreeNode root) {
        List res = new LinkedList();
        dfs(root,res);
        return res;
    }
    private void dfs(TreeNode root ,List res){
        if(root == null){
            return;
        }
        res.add(root.val);
        dfs(root.left,res);
        dfs(root.right,res);
    }
}

中序:

class Solution {
    public List inorderTraversal(TreeNode root) {
        ArrayList res = new ArrayList();
        dfs(root,res);
        return res;
    }
    private void dfs(TreeNode root ,List res){
        if(root == null){
            return;
        }
        dfs(root.left,res);
        res.add(root.val);
        dfs(root.right,res);
    }
}

后序:

class Solution {
    public List postorderTraversal(TreeNode root) {
        List res = new ArrayList();
        dfs(root,res);
        return res;
    }
    private void dfs(TreeNode root , List res){
        if(root == null){
            return;
        }
        dfs(root.left,res);
        dfs(root.right,res);
        res.add(root.val);
    }
}

②各自为营的迭代法(每种都有自己的特点,不具有模板性)

前序:

class Solution {
    public List preorderTraversal(TreeNode root) {
        List res = new LinkedList();
        Stack stack = new Stack();
        if(root == null){
            return res;
        }
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            res.add(node.val);
            if(node.right != null){
                stack.push(node.right);
            }
            if(node.left != null){
                stack.push(node.left);
            }
        }
        return res;
    }
}

中序:

class Solution {
    public List inorderTraversal(TreeNode root) {
        List res = new LinkedList();
        Stack stack = new Stack();
        if(root == null){
            return res;
        }
        //需要使用指针cur,来解决访问节点和处理节点不一致的问题
        TreeNode cur = root;
        while(cur != null || !stack.isEmpty()){
            if(cur != null){
                stack.push(cur);
                cur = cur.left;
            }else{
                cur = stack.pop();
                res.add(cur.val);
                cur = cur.right;
            }
        }
        return res;
    }
}

后序:

class Solution {
    //迭代1:各自为营的迭代(前序和后序有一点点关系)把 中左右——>中右左——>翻转成为 左右中(后序)
    public List postorderTraversal(TreeNode root) {
        List res = new ArrayList();
        Stack stack = new Stack();
        if(root == null){
            return res;
        }
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            res.add(node.val);
            if(node.left != null){
                stack.push(node.left);
            }
            if(node.right != null){
                stack.push(node.right);
            }
        }
        Collections.reverse(res);
        return res;
    }
}

③模板迭代

前序:

class Solution {
     public List preorderTraversal(TreeNode root) {
         List res = new LinkedList();
         Stack stack = new Stack();
         if(root == null){
             return res;
         }
         stack.push(root);
         while(!stack.isEmpty()){
             TreeNode node = stack.pop();
             if(node != null){
                 if(node.right != null){
                     stack.push(node.right);
                 }
                 if(node.left != null){
                     stack.push(node.left);
                 }
                 stack.push(node);
                 stack.push(null);
             }else{
                 res.add(stack.pop().val);
             }
         }
         return res;
     }
 }

中序:

class Solution {
    public List inorderTraversal(TreeNode root) {
        List res = new LinkedList();
        Stack stack = new Stack();
        if(root == null){
            return res;
        }
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            if(node != null){
                if(node.right != null){
                    stack.push(node.right);
                }
                    stack.push(node);
                    stack.push(null);
                if(node.left != null){
                    stack.push(node.left);
                }
            }else{
                res.add(stack.pop().val);
            }
        }
        return res;
    }   
}

后序:

class Solution {
    public List postorderTraversal(TreeNode root) {
        List res = new ArrayList();
        Stack stack = new Stack();
        if(root == null){
            return res;
        }
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            if(node != null){
                stack.push(node);
                stack.push(null);
                if(node.right != null){
                    stack.push(node.right);
                }
                if(node.left != null){
                    stack.push(node.left);
                }
            }else{
                res.add(stack.pop().val);
            }
        }
        return res;
    }
}

总结:模板迭代中,先序、中序、后序遍历只有下面这一块的两行代码有变动,好记、但是不好理解。

① 
stack.push(node);
stack.push(null);
②
if(node.right != null){
     stack.push(node.right);
}
③
if(node.left != null){
     stack.push(node.left);
}

①、②、③三部分根据先序、后序、中序遍历的顺序,那一部分先访问到,就让它最后入栈即可。

模板迭代的整体思想就是,如果访问到 null ,则栈下一个元素就是要弹出来加入结果集的元素。

你可能感兴趣的:(二叉树专题,leetcode,算法,递归法,java)