二叉树的遍历方法汇总

1. 二叉树的前序遍历

题解一:递归

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        recurPreorder(root, res);
        return res;
    }

    public void recurPreorder(TreeNode root, List<Integer> res) {
        if (root == null) {
            return;
        }
        res.add(root.val);
        recurPreorder(root.left, res);
        recurPreorder(root.right, res);
    }
}

复杂度分析

  • 时间复杂度:O(n) ,其中n 是二叉树的节点数。每个节点都恰好被遍历一遍。
  • 空间复杂度:O(n) ,为递归过程中栈的开销,平均情况下为O(logn),最坏情况下为O(n)。

题解二:非递归

前序遍历的遍历顺序是“根左右”,所以有以下思路。

算法思路:

  1. 令一个node 指向root ,开始遍历树
  2. 如果node 不为空,将其入栈,添加其值到列表中,并指向其左子节点。
  3. 如果node 为空说明左子树已经遍历到底,将node 赋值为stack 的弹栈,然后令node 指向其右节点。
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();

        Deque<TreeNode> stack = new LinkedList<>();
        TreeNode node = root;
        while (node != null || !stack.isEmpty()) {
            while (node != null) {
                list.add(node.val);
                stack.push(node);
                node = node.left;
            }
            node = stack.pop();
            node = node.right;
        }
        return list;
    }
}

2. 二叉树的中序遍历

题解一:递归

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

题解二:非递归

左根右

算法思路:

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

3. 二叉树的后序遍历

题解一:递归

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        recurPostorder(root, list);
        return list;
    }

    public void recurPostorder(TreeNode root, List<Integer> list) {
        if (root == null) {
            return;
        }
        recurPostorder(root.left, list);
        recurPostorder(root.right, list);
        list.add(root.val);
    }
}

题解二:非递归

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        if (root == null) {
            return list;
        }

        Deque<TreeNode> stack = new LinkedList<>();
        TreeNode pre = null;
        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            if (root.right == null || root.right == pre) {
                list.add(root.val);
                pre = root;
                root = null;
            } else {
                stack.push(root);
                root = root.right;
            }
        }
        return list;
        
    }
}

算法思路:与前序遍历的非递归实现思路相似。后序遍历的遍历顺序是“左右根”,那么我们只需用类似前序遍历的算法,顺序是“根右左”,然后利用集合的reverse 将整个集合颠倒就变成了“左右根”,也就是后序遍历。

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        //左 右 根 <== 先访问 根 右 左 反转 (即和前序异曲同工)
        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                list.add(root.val);
                stack.push(root);
                root = root.right;//和前序的差异,前序是向左走
            }
            TreeNode node = stack.pop();
            root = node.left;//和前序的差异
        }
        Collections.reverse(list);
        return list;
    }
}

Collections.reverse(list) : 翻转list 列表。

4.二叉树的层序遍历

题解

利用队列,完成二叉树的层次遍历,算法思路:

  1. 如果根节点不为空则入队,否则直接返回一个空数组;
  2. 在队列不为空的情况下,将节点出队,并将节点的值记录到List 集合中;
  3. 分别判断出队节点的左右儿子是否为空,不为空的入队;
  4. 重复2、3 直至队列为空
  5. 将集合遍历放到结果数组中,输出结果。
class Solution {
    public int[] levelOrder(TreeNode root) {
        if (root == null) return new int[0];
        Deque<TreeNode> queue = new LinkedList<>();
        List<Integer> list = new ArrayList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            list.add(node.val);
            if (node.left != null) queue.add(node.left);
            if (node.right != null) queue.add(node.right);
        }
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            res[i] = list.get(i);
        }
        return res;
    }
}
posted @ 2022-04-09 20:07  李同学的跋涉  阅读(86)  评论(0)    收藏  举报