Java二叉树层序遍历中迭代法和递归法的深入分析总结

前言

之前我写过一篇文章详细分析了 Java 所有前中后序遍历二叉树全方法归纳总结(深度优先搜索),有兴趣的同学可以看一看。当然如果有帮助可以点一个赞,本人也是一个初学萌新,可能有些地方理解的不是很到位,欢迎大家批评指正。

之前的前中后序遍历都属于深度优先搜索,层序遍历则是广度优先搜索。也是主要分为两种思路来实现:迭代法实现和递归法实现。

迭代法

迭代法的思想是用队列的先入先出来实现一层一层的输出值到结果集中。主要注意以下四点:

  1. 一次循环只处理这一层的节点数据。
  2. 在处理这一层节点的时候,要把当前层每个节点的左右孩子加入到队列中(进行非空判断),以供下一次循环作为下一层节点被处理。
  3. 在循环开始的时候读取队列q的长度来确定这一层有多少节点,确定了这一层循环中要处理的节点个数。【因为边处理节点的时候还会把左右孩子再加入队列,要在最开始确定好处理的个数,不能把下一层要处理的提前处理了】
  4. 当队列为空就证明最深层也被遍历完了,循环结束。

代码如下:

// 使用队列迭代来实现
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
       List<List<Integer>> list = new ArrayList<>();
        // 使用队列先进后出的特点一层一层存放数据
        Queue<TreeNode> q = new LinkedList<>();
        if (root == null) {
            return list;
        }
        // 根节点入队列
        q.offer(root);
        while (!q.isEmpty()) {
            // 确定当前队列的长度(当前层的节点长度)
            int size = q.size();
            List<Integer> level = new ArrayList<>();
            // 处理这一层所有的节点,存入数组
            for (int i = 0; i < size; i++) {
                // 依次弹出这一层的所有节点,并将值存入数组
                TreeNode temp = q.poll();
                level.add(temp.val);
                // 依次将这些节点的左右孩子也加入队列中(下一次while循环的时候构成下一层的节点)
                if (temp.left != null) {
                    q.offer(temp.left);
                }
                if (temp.right != null) {
                    q.offer(temp.right);
                }
            }
            // 把这一层的结果存入集合
            list.add(level);
        }
        return list;
    }   
}

递归法

递归法的处理顺序是先把左孩子那一路的每一层全部处理完,再去处理右孩子的每一层

  1. 确定递归函数的参数和返回值:传入根节点、结果集和深度标识deep。
  2. 确定终止条件: 当节点为空终止。
  3. **确定单层递归的逻辑:**①深度标识符+1表示进了新的一层;②根据深度标识符来判断结果集中这一层的数组是否创建,没有创建的话先创建数组;③在结果集中 当前深度标识符所对应的数组中 加入本节点的值,并让这个节点的左右孩子继续递归下去。
// 使用递归来实现
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
       List<List<Integer>> list = new ArrayList<>();
        order(root, list, 0);
        return list;
    }
    public static void order(TreeNode node, List<List<Integer>> result, int deep) {
        if (node == null) {
            return;
        }
        deep++;
        //当层级增加时,list的size也要增加,利用list的size进行层级界定
        if (result.size() < deep) {
            result.add(new ArrayList<>());
        }
        // 在当前深度的层级加入节点值
        result.get(deep - 1).add(node.val);
        // 左孩子
        order(node.left, result, deep);
        // 右孩子
        order(node.right, result, deep);
    }   
}

总结

先总结一下两个方法之间的区别:

  • 迭代法的处理顺序是先处理完第一层的所有数据,再去处理第二层等等,以此类推。

  • 递归法的处理顺序是先把左孩子那一路的每一层全部处理完,再去处理右孩子的每一层

递归法跟迭代法的思路不同,他并不是一层全部处理完才处理下一层的,每层递归在处理当前节点的时候都会有一个deep的深度标识,所以可以把数据准确的放进对应深度的集合中,他只需要保证数据存放的先后顺序是对的就行,并不需要一次性把这一层的数据放完!

举一个例子来说,递归法更像是一张白纸上同时写好几行字,你可以第一行写几个字就直接在第二行上开始写,等下面每行都写了几个字后再继续回到第一行再写。只需要保证每一行写字的顺序不要错,并且每一行的内容不能缺失就行了,并不关心你是否能一口气把第一行写完再写第二行。这就是二叉树层序遍历迭代法和递归法的区别

你可能感兴趣的:(数据结构,java,数据结构)