如何按层遍历二叉树?

322 阅读3分钟

前言

本文主要介绍如何按层次遍历一棵二叉树,并把遍历的结果放到集合中。

需求描述

给出一个二叉树的根节点 root ,然后返回其节点值的层序遍历,每一层从左到右进行遍历,返回数据时,从下往上进行返回。

示例如下:

如下图所示,拿到一个二叉树后,从下往上、从左到右按层进行遍历,输出结果为:[[8, 9], [4, 5, 6, 7], [2, 3], [1]]

思路分析

之前我们在遍历二叉树时,都是从上往下进行遍历,其实题目中可以从上往下进行遍历好,然后把结果再做一个逆序排列就好了。

按照示例图中,先来看下每一层遍历的结果是什么:

  • 第1层:[1]
  • 第2层:[2, 3]
  • 第3层:[4,5,6,7]
  • 第4层:[8, 9]

那怎么把每一层的节点值放到集合中呢?

  • 步骤1
    • 先把头结点放入一个队列中
  • 步骤2
    • 判断队列中的sizesize是多少,则就执行步骤3多少次
  • 步骤3
    • 准备好一个集合,用来准备队列中弹出的元素,每一层对应一个集合,将弹出的元素放入集合中。
    • 判断弹出元素是否有子节点,如果有的话,将子节点加入队列中。

用示例图中的二叉树,来看一下具体过程:

  1. 节点1进入队列,此时队列的size1,执行步骤 2``1次,将节点1弹出,创建一个集合将节点的值放进入。
  2. 将节点1的子节点加入队列,从左往右,节点2先进入队列,节点3后进入队列。
  3. 此时队列长度为2,现将节点2弹出,将子节点4和子节点5放入队列,再将节点3弹出,将节点3的子节点6、7放入队列,此时队列中的数据为4、5、6、7,创建一个集合将弹出去的节点2、3放进去。
  4. 依次类推,安装这个步骤,就能实现一棵二叉树的层次遍历。

经过上面的步骤,我们已经分析出了如何从上往下按层次收集一棵二叉树的节点,那么如何逆序呢?

因为收集起来的元素是放入一个集合中的,可以直接把集合进行反转即可。

思路优化

但是集合的反转会带来额外的时间开销,有没有更好的办法呢?

我们可以使用一个链表(LinkedList)来代替集合(ArrayList),在往前面放入一个元素时,链表只需要把节点间的关系关联上即可,而集合需要一次一次的挪动元素。

例如,现在集合中有4个元素[1,2,3,4],如果想在1元素之前加入一个数的话,1,2,3,44个元素都需要往后挪动一下,如果是链表的话,直接插入即可,所以使用链表效率会更高一些。

代码实现

根据上面的思路分析,来看一下代码是如何实现的:

首先定义二叉树的节点,代码如下:

public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(int val) {
        this.val = val;
    }
}

遍历二叉树的代码如下:

public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> ans = new LinkedList<>();
    if (root == null) {
        return ans;
    }
    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        int size = queue.size();
        List<Integer> curAns = new LinkedList<>();
        for (int i = 0; i < size; i++) {
            TreeNode curNode = queue.poll();
            curAns.add(curNode.val);
            if (curNode.left != null) {
                queue.add(curNode.left);
            }
            if (curNode.right != null) {
                queue.add(curNode.right);
            }
        }
        ans.add(0, curAns);
    }
    return ans;
}

总结

本文主要介绍如何按层次遍历一棵二叉树,总体来说这个题目还是很简单的,当然还有其他更简单的实现方案,这里就不再介绍了~