二叉树层序遍历分层[递归迭代两种思想+三种解法]

层序遍历分层的递归迭代解法

  • 前言
  • 一、二叉树层序遍历分层
  • 二、递归与迭代
  • 总结
  • 参考文献

前言

层序遍历作为二叉树遍历的基本遍历,一般来说只能用迭代来解。但是分层输出则既可用迭代,又可配合level用前序遍历来解。

一、二叉树层序遍历分层

二叉树层序遍历分层[递归迭代两种思想+三种解法]_第1张图片

二、递归与迭代

package com.xhu.offer.everyday;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

//层序遍历
public class LevelOrder {
    /*
    target:对二叉树进行层次遍历。
    如何拿到每一层节点?每一层节点都是上层节点的左右孩子,只要有序拿到上层parent,就能有序拿到下层children。以root开始,以队列来体现有序进出。
    如何明确的分层?记录每一层的size,取一个就减一个直到为0,再取队列的size作为当前层的cnt.
     */
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> rs = new ArrayList<>();

        if (null == root) return rs;

        Queue<TreeNode> cur = new LinkedList<>();
        cur.add(root);//bug1:root为null时,也会作为TreeNode的null状态加入队列。
        int cnt = cur.size();

        List<Integer> el = new ArrayList<>();
        while (!cur.isEmpty()) {
            TreeNode node = cur.poll();
            el.add(node.val);

            if (node.left != null) cur.add(node.left);
            if (null != node.right) cur.add(node.right);

            if (--cnt == 0) {
                rs.add(el);
                el = new ArrayList<>();

                cnt = cur.size();
            }
        }
        return rs;
    }

    // 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;
        }
    }

}

/*
用TreeNode数组 + len + cur_index来替代队列
每层有各自的list和cur_index.
 */
class LevelOrder2 {
    /*
    target:对二叉树进行层次遍历。
    如何拿到每一层节点?每一层节点都是上层节点的左右孩子,只要有序拿到上层parent,就能有序拿到下层children。以root开始,以队列来体现有序进出。
    如何明确的分层?每层有各自的list和cur_index
     */
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> rs = new ArrayList<>();

        if (null == root) return rs;

        TreeNode[] cur = new TreeNode[2000];
        cur[0] = root;
        int len = 1, idx = 0, cnt = 1;

        List<Integer> el = new ArrayList<>();
        while (len != idx) {
            TreeNode node = cur[idx++];
            el.add(node.val);

            if (node.left != null) cur[len++] = node.left;
            if (null != node.right) cur[len++] = node.right;

            if (--cnt == 0) {
                rs.add(el);
                el = new ArrayList<>();

                cnt = len - idx;
            }
        }
        return rs;
    }

    // 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;
        }
    }

}

/*
鉴于每一层都放到各自的list中(结果要求),所以采用递归配合level,把节点放入相应的list即可。
 */
class LevelOrder3 {
    /*
    鉴于每一层都放到各自的list中(结果要求),所以采用递归配合level,把节点放入相应的list即可。
    */
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> rs = new ArrayList<>();

        if (null == root) return rs;

        order(root, rs, 0);

        return rs;
    }

    /**
     * 递归遍历,配合level完成各层到各家。
     *
     * @param root
     * @param rs
     * @param level
     */
    private void order(TreeNode root, List<List<Integer>> rs, int level) {
        if (root == null) return;
        //前序遍历,第一次达到这种深度,则生成当前层的list。
        if (level == rs.size()) {
            List<Integer> el = new ArrayList<>();
            rs.add(el);
        }
        List<Integer> cur = rs.get(level);
        cur.add(root.val);

        order(root.left, rs, level + 1);
        order(root.right, rs, level + 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;
        }
    }

}

总结

1)层序遍历:直接迭代+队列。
2)层序遍历分层:迭代+计数;递归+level。
3)层序遍历时,秉着基本数据类型或jvm层面的数组类型快,可用TreeNode数组来代替Queue这种类,可以提高速度。

参考文献

[1] LeetCode 二叉树的层序遍历分层

你可能感兴趣的:(数据机构与算法,二叉树,层序遍历,Java,迭代,递归)