二叉树遍历(前+中+后+层次)

144 阅读1分钟

二叉树类的定义

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */

144. 二叉树的前序遍历

遍历顺序: 根-左-右

方法一 递归

class Solution {
    List<Integer> list = new LinkedList<>();
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root == null)return list;
        list.add(root.val);
        preorderTraversal(root.left);
        preorderTraversal(root.right);
        return list;
    }
}

方法二 迭代

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list = new LinkedList<>();
        if(root == null)return list;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while(!stack.empty() || cur!=null){
            while(cur!=null){
                stack.push(cur);
                list.add(cur.val); //插入节点值
                cur = cur.left;
            }
            cur = stack.pop();
            cur = cur.right;
        }
        return list;
    }
}

image.png (取自网图)

前序遍历和中序遍历的区别在于何时将树节点值加入链表List,即 List.add(cur,val) ,前序遍历在节点入栈时将节点值插入,中序遍历在节点出栈时将节点值插入。

前序、中序遍历思路

设置遍历节点cur,从根节点开始。

一. 依次入栈左子树根节点直至为空;

1,2,4依次入栈

二. 栈顶出栈,遍历该节点右子树,重复步骤一;

4出栈,2出栈,5入栈,5出栈,1出栈,3入栈,6入栈,3出栈,7入栈

94. 二叉树的中序遍历

遍历顺序: 左-根-右

方法一 递归

class Solution {
    List<Integer> list = new LinkedList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
        if(root == null)return list;
        inorderTraversal(root.left);
        list.add(root.val);
        inorderTraversal(root.right);
        return list;
    }
}

方法二 迭代

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new LinkedList<>();
        if(root == null)return list;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while(!stack.empty() || cur!=null){
            while(cur!=null){
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();
            list.add(cur.val); //插入节点值
            cur = cur.right;
        }
        return list;
    }
}

145. 二叉树的后序遍历

遍历顺序: 左-右-根

方法一 递归

class Solution {
    List<Integer> list = new LinkedList<>();
    public List<Integer> postorderTraversal(TreeNode root) {
        if(root == null)return list;
        postorderTraversal(root.left);
        postorderTraversal(root.right);
        list.add(root.val);
        return list;
    }
}

方法二 迭代

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new LinkedList<>();
        if(root == null)return list;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while(!stack.empty() || cur!=null){
            while(cur!=null){
                stack.push(cur);
                list.add(cur.val); //插入节点值
                cur = cur.right; //先右
            }
            cur = stack.pop();
            cur = cur.left;  // 后左
        }
        Collections.reverse(list); 
        //or LinkedList<> list = new LinkedList<>(); list.addFirst();
        return list;
    }
}

后序遍历顺序为:左-右-根

而前序遍历顺序为:根-左-右,将前序的遍历顺序更改为:根-右-左,将链表反转后输出,此时输出顺序恰好为左右根,符合后序遍历

三类遍历时间空间复杂度

时间复杂度:O(n),n为树的节点个数

空间复杂度:O(n),平均情况下为 O(logn),最坏情况下树呈现链状,为 O(n)。

102. 二叉树的层序遍历

image.png

输出顺序: 1,2,3,4,5,6,7

输出格式:[[1],[2,3],[4,5,6,7]]

运用BFS思想遍历(BFS还应用于最短路径搜索)

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> output = new ArrayList<>();
        if(root == null)return output;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            int n = queue.size();
            ArrayList<Integer> list = new ArrayList<>();
            for(int i=0; i<n; i++){
                TreeNode temp = queue.poll();
                if(temp.left!=null)queue.offer(temp.left);
                if(temp.right!=null)queue.offer(temp.right);
                list.add(temp.val);
            }
            output.add(list);
        }
        return output;
    }
}

层次遍历思路

借助队列先进先出的特性,依次入队二叉树的每一层节点,从根节点开始入队

一. 出队,将节点值插入List,依次入队该节点的左右子节点;

 1入队;1出队,23入队;2出队,45入队,3出队,67入队;4567出队.

二. 重复步骤一直至队列为空;

时间空间复杂度

时间复杂度:每个点进队出队各一次,故渐进时间复杂度为 O(n)。

空间复杂度:队列中元素的个数不超过 n 个,故渐进空间复杂度为 O(n)。

PS:代码思路均来自LeetCode解析