首页 > 其他分享 >全面解析二叉树的层次遍历及其实现

全面解析二叉树的层次遍历及其实现

时间:2024-12-04 12:28:25浏览次数:7  
标签:遍历 TreeNode current right 二叉树 解析 root left


二叉树的层次遍历(Level Order Traversal)是以层为单位,从根节点开始逐层访问节点的遍历方法。在很多树的算法中,层次遍历是基础。本文将详细解析层次遍历的原理,提供Java和Python的实现,以及常见扩展应用。


一、层次遍历的定义与特点

1.1 什么是层次遍历?

层次遍历是指按照二叉树的层级,从上到下、从左到右依次访问每个节点。例如,对于如下二叉树:

       1
      / \
     2   3
    / \   \
   4   5   6

层次遍历的访问顺序为:1 -> 2 -> 3 -> 4 -> 5 -> 6

1.2 层次遍历的特点

  1. 遍历结果以层为单位。
  2. 借助队列(Queue)实现,先进先出(FIFO)保证节点按层顺序访问。
  3. 可扩展为分层输出或锯齿形遍历。

二、层次遍历的实现

2.1 基本步骤

  1. 初始化一个队列,将根节点加入队列。
  2. 循环执行以下操作,直到队列为空:
    • 从队列中取出一个节点,访问它。
    • 如果该节点有左子节点,将其加入队列。
    • 如果该节点有右子节点,将其加入队列。

2.2 Java实现

树节点定义
class TreeNode {
    int val;
    TreeNode left, right;

    TreeNode(int val) {
        this.val = val;
    }
}
层次遍历方法
import java.util.LinkedList;
import java.util.Queue;

public class BinaryTreeLevelOrder {
    public static void levelOrder(TreeNode root) {
        if (root == null) return;

        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);

        while (!queue.isEmpty()) {
            TreeNode current = queue.poll(); // 取出队首节点
            System.out.print(current.val + " "); // 访问节点

            if (current.left != null) {
                queue.add(current.left); // 加入左子节点
            }

            if (current.right != null) {
                queue.add(current.right); // 加入右子节点
            }
        }
    }

    public static void main(String[] args) {
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(4);
        root.left.right = new TreeNode(5);
        root.right.right = new TreeNode(6);

        System.out.println("层次遍历结果:");
        levelOrder(root);
    }
}

输出结果

层次遍历结果:
1 2 3 4 5 6

2.3 Python实现

树节点定义
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
层次遍历方法
from collections import deque

def level_order(root):
    if not root:
        return

    queue = deque([root])
    while queue:
        current = queue.popleft()  # 取出队首节点
        print(current.val, end=" ")  # 访问节点

        if current.left:
            queue.append(current.left)  # 加入左子节点
        if current.right:
            queue.append(current.right)  # 加入右子节点

# 构建二叉树
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
root.right.right = TreeNode(6)

print("层次遍历结果:")
level_order(root)

输出结果

层次遍历结果:
1 2 3 4 5 6

三、按层分组输出的层次遍历

在某些场景下,我们需要按层将节点分组,例如:

层次分组遍历结果:
[[1], [2, 3], [4, 5, 6]]

3.1 Java实现

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

public class LevelOrderByLayer {
    public static List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<>();
        if (root == null) return result;

        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);

        while (!queue.isEmpty()) {
            int levelSize = queue.size(); // 当前层节点数量
            List<Integer> currentLevel = new ArrayList<>();

            for (int i = 0; i < levelSize; i++) {
                TreeNode current = queue.poll();
                currentLevel.add(current.val);

                if (current.left != null) {
                    queue.add(current.left);
                }

                if (current.right != null) {
                    queue.add(current.right);
                }
            }

            result.add(currentLevel);
        }

        return result;
    }

    public static void main(String[] args) {
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(4);
        root.left.right = new TreeNode(5);
        root.right.right = new TreeNode(6);

        System.out.println("层次分组遍历结果:");
        System.out.println(levelOrder(root));
    }
}

3.2 Python实现

from collections import deque

def level_order_by_layer(root):
    if not root:
        return []

    result = []
    queue = deque([root])

    while queue:
        level_size = len(queue)
        current_level = []

        for _ in range(level_size):
            current = queue.popleft()
            current_level.append(current.val)

            if current.left:
                queue.append(current.left)
            if current.right:
                queue.append(current.right)

        result.append(current_level)

    return result

# 构建二叉树
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
root.right.right = TreeNode(6)

print("层次分组遍历结果:")
print(level_order_by_layer(root))

输出结果

层次分组遍历结果:
[[1], [2, 3], [4, 5, 6]]

四、扩展应用

  1. 寻找二叉树的最大宽度
    • 在层次遍历中记录每层节点数量,取最大值。
  2. 锯齿形层次遍历(Z字形遍历)
    • 奇数层从左到右,偶数层从右到左访问节点。
  3. 判断完全二叉树
    • 使用层次遍历,确保某层出现空节点后不再有非空节点。

五、总结

层次遍历是二叉树遍历的重要方法,其实现简单且应用广泛。通过本文的学习,你掌握了:

  1. 层次遍历的基本实现。
  2. 按层分组输出的扩展。
  3. 常见的扩展应用场景。

层次遍历是树形结构问题的基础,建议在实际问题中多加练习,以便深入理解和灵活应用。

标签:遍历,TreeNode,current,right,二叉树,解析,root,left
From: https://blog.csdn.net/zhaoshanshan168/article/details/144206599

相关文章

  • 全网最全情景,深入浅出解析JavaScript数组去重:数值与引用类型的全面攻略
    目录全网最全情景,深入浅出解析JavaScript数组去重:数值与引用类型的全面攻略一、引言:我们为什么需要关注数组去重?二、数值类去重1、使用Set去重2、遍历+includes()3、使用filter()和indexOf()4、使用reduce()5、嵌套数组去重:结合flat()三、引用类去重——去除......
  • 深入解析Android OTA升级中的版本号管理与build.prop文件生成机制
    前言OTA(Over-The-Air)升级过程中,版本号扮演着至关重要的角色。从低版本向高版本的升级操作,必须依赖于当前设备的属性信息,其中版本号就是核心要素之一为了深入探究build.prop文件的生成机制,我们在build/目录下进行了广泛的搜索,特别是针对ro.build.display.id这一关键属性。......
  • 【工具篇】AI工具生态全景解析:提升生产力利器
    大家不必再东奔西走去找各种工具或者去AI导航站一个一个去试,下面挑选出来的就是各个领域最好的,省去大家的时间和精力。「工欲善其事,必先利其器。」 AI时代,掌握高效的智能工具,就是抢占技术制高点。本文将全面揭秘AI工具生态,为你开启智能生产力新世界。一、AI大语言模型:智能......
  • LCR 043.完全二叉树(中等)(主站919)
    https://leetcode.cn/problems/NaqhDT/https://leetcode.cn/problems/complete-binary-tree-inserter/难度:☆☆☆题目:完全二叉树是每一层(除最后一层外)都是完全填充(即,节点数达到最大,第n层有2n-1个节点)的,并且所有的节点都尽可能地集中在左侧。设计一个用完全二叉树......
  • 根据元素ID遍历树形结构,查找到所有父元素ID [代码]
    functionfindParentIds(elementId,treeData){constparentIds=[];functiontraverse(node){if(node.id===elementId){returntrue;}if(node.children){for(constchildofnode.children){if(traverse(child))......
  • 二叉树的概念及其在Java中的实现
    文章目录什么是二叉树?二叉树的特点:二叉树的定义Java中实现二叉树1.定义二叉树节点2.创建二叉树类并添加插入方法3.遍历方法4.查找特定值的方法什么是二叉树?二叉树(BinaryTree)是一种非线性数据结构,它由一组有限数量的节点组成,这组节点或者为空(即没有节点),或者......
  • 利用注解和 AOP 实现权限认证:原理、实践与代码解析
    目录利用注解和AOP实现权限认证:原理、实践与代码解析一、核心思想二、目录三、代码示例(一)项目搭建与依赖引入(基于SpringBoot)(二)自定义权限注解(三)AOP切面类实现(四)远程权限服务接口(Feign示例)(五)在业务方法中应用注解一、核心思想在现代软件开发中,权限认证是保......
  • QScan工具使用全解析:提升渗透效率的必备工具
    免责声明本文章仅供学习交流使用,旨在帮助广大安全爱好者提升技术水平和分享经验。文中所提到的任何工具、脚本、方法或案例,均用于合法范围内的网络安全学习与研究,禁止将其用于任何非法目的。请严格遵守相关法律法规,未经授权不得对他人系统进行测试或操作。任何因滥用文章......
  • iOS应用性能监控与分析技术深度解析
    在移动应用开发领域,性能优化是确保应用流畅运行和用户满意度的重要因素。iOS应用性能监控与分析技术能够帮助开发者及时发现和解决性能瓶颈,提升应用的整体质量。本文将聚焦于iOS应用性能监控与分析的几个关键方面,包括Crash监控、响应时间分析、内存泄漏检测等。Crash监控Crash......
  • [技术资料] 深入解析Spring Boot自动配置的核心原理与实现机制
    SpringBoot的最大优势之一便是其自动化配置(Auto-Configuration),通过自动配置,开发者无需手动配置大量的XML文件或Java配置类,SpringBoot会根据项目中的依赖和环境自动加载并配置相关组件。这个功能大大简化了应用程序的搭建和开发流程。在本文中,我们将详细探讨SpringBoot如何实......