力扣一题 二叉树的前序、中序、后序遍历(递归+迭代)

180 阅读2分钟

u=1226221302,658571283&fm=253&fmt=auto&app=120&f=JPG.webp

对于二叉树而言,主要有三种遍历方式:前序遍历、中序遍历和后序遍历 (当然,还有层序遍历,但不在本的讨论范围内)。前中后是对于根节点而言的,前序就是“先根再左最后右”,而中序就是“先左再根最后右”,后序自然就是“先左再右最后根”。

实现二叉树的遍历,主要有递归和迭代两种方法,递归方法相对较为简单,这里就不做说明了,直接上代码

递归

// 前序
class Solution {
    public List<Integer> res=new ArrayList<>();
    public List<Integer> preorderTraversal(TreeNode root) {
        method(root);
        return res;
    }
    void method(TreeNode root){
        if(root==null) return;
        res.add(root.val);
        method(root.left);
        method(root.right);
    }
}
​
// 中序
class Solution {
    List<Integer>list=new ArrayList();
    public List<Integer> inorderTraversal(TreeNode root) {
        helper(root);
        return list;
    }
    void helper(TreeNode root){
        if(root==null) return ;
        helper(root.left);
        list.add(root.val);
        helper(root.right);
    }
}
​
// 后序
class Solution {
    List<Integer>res=new ArrayList();
    public List<Integer> postorderTraversal(TreeNode root) {
        helper(root);
        return res;
    }
    void helper(TreeNode root){
        if(root==null) return;
        helper(root.left);
        helper(root.right);
        res.add(root.val);
    }
}

迭代

迭代相对于递归难了一点点,但其实也比较好理解,前中后序遍历都是借助栈“先进后出,后进先出”这个特性来完成的

前序

前序遍历是“根->左->右",我们从根节点开始不断往其左子节点遍历,将遍历到的值加入结果集中。同时借助一个栈来将遍历过的节点压入栈中,这样在遍历到左节点为null时,就可以弹出栈中的一个节点,从这个节点的右节点开始遍历

public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer>res=new ArrayList();
        Deque<TreeNode>stack=new LinkedList();
        TreeNode node=root;
        while(node!=null||!stack.isEmpty()){
            if(node!=null){
                res.add(node.val);
                stack.push(node);
                node=node.left;
            }else{
                node=stack.pop();
                node=node.right;
            }
        }
        return res;
    }

中序

中序遍历的思路跟前序遍历的差不多,主要的不同点在于,中序遍历的顺序为"左->根->右",所以不能像前序遍历那样在遍历到节点时就将节点的值加入结果集,而是在将节点从栈中弹出时再将节点值加入结果集

public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer>res=new ArrayList();
        Deque<TreeNode>stack=new LinkedList();
        TreeNode node=root;
        while(node!=null||!stack.isEmpty()){
            if(node!=null){
                stack.push(node);
                node=node.left;
            }else{
                node=stack.pop();
                res.add(node.val);
                node=node.right;
            }
        }
        return res;
    }

后序

后序遍历的思路就跟上面两种稍有不同了,因为后序的遍历顺序是"左->右->根",按照前面两种方法是无法实现这个遍历顺序的,那么我们可以转变思路,将“左->右->根"变为"根->右->左" ,之后将遍历到的值采用头插入法插入结果集即可,其它的实现都跟前序遍历一致

public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer>res=new ArrayList();
        TreeNode node=root;
        Deque<TreeNode>stack=new LinkedList();
        while(node!=null||!stack.isEmpty()){
            if(node!=null){
                res.add(0,node.val);
                stack.push(node);
                node=node.right;
            }else{
                node=stack.pop();
                node=node.left;
            }
        }
        return res;
    }