【java-数据结构】Java 二叉树:代码世界里的神奇树形魔法

【java-数据结构】Java 二叉树:代码世界里的神奇树形魔法
在这里插入图片描述

我的个人主页
我的专栏:人工智能领域、java-数据结构、Javase、C语言,希望能帮助到大家!!!点赞👍收藏❤

在这里插入图片描述


在这里插入图片描述

前言

在计算机科学领域,数据结构是算法实现的基石,而二叉树则是其中一颗璀璨的明珠。它以独特的树形结构,在众多场景中发挥着关键作用。二叉树由节点组成,每个节点最多包含两个子节点,这种简洁而强大的设计,使得数据的存储、检索与处理变得高效且有序。无论是数据库索引、编译器的语法分析,还是人工智能中的决策树算法,都离不开二叉树的身影。在Java编程世界里,掌握二叉树的生成与操作是迈向高级编程的重要一步。通过使用Java语言来构建二叉树,不仅能够深入理解数据结构的底层原理,还能提升解决复杂问题的能力。接下来,我们将一步步深入探索如何在Java中实现二叉树,从节点的定义到树的构建,再到各种遍历与操作方法,揭开这一重要数据结构的神秘面纱。

一:什么是二叉树

二叉树是一种每个节点最多有两个子节点的树形数据结构,这两个子节点通常被称为左子节点和右子节点。这种简洁而强大的结构,在许多算法和数据处理场景中发挥着关键作用。
树是⼀种⾮线性的数据结构,它是由n(n>=0)个有限结点组成⼀个具有层次关系的集合。把它叫做树是因为它看起来像⼀棵倒挂的树,也就是说它是根朝上,⽽叶朝下的。它具有以下的特点:

  • 有⼀个特殊的结点,称为根结点,根结点没有前驱结点
  • 除根结点外,其余结点被分成M(M > 0)个互不相交的集合T1、T2、…、Tm,其中每⼀个集合Ti
    (1 <= i <= m) ⼜是⼀棵与树类似的⼦树。每棵⼦树的根结点有且只有⼀个前驱,可以有0个或多个后
  • 树是递归定义的。

注意:树形结构中,⼦树之间不能有交集,否则就不是树形结构


那么怎么区分什么是树,什么不是树呢?
请看下面图片:

在这里插入图片描述

一些二叉树重要的概念,以下面这棵树为例:
在这里插入图片描述
  1. 结点的度:⼀个结点含有⼦树的个数称为该结点的度; 如上图:A的度为6
  2. 树的度:⼀棵树中,所有结点度的最⼤值称为树的度; 如上图:树的度为6
  3. 叶⼦结点或终端结点:度为0的结点称为叶结点; 如上图:B、C、H、I…等节点为叶结点
  4. 双亲结点或⽗结点:若⼀个结点含有⼦结点,则这个结点称为其⼦结点的⽗结点; 如上图:A是B的⽗
    结点
  5. 孩⼦结点或⼦结点:⼀个结点含有的⼦树的根结点称为该结点的⼦结点; 如上图:B是A的孩⼦结点
  6. 根结点:⼀棵树中,没有双亲结点的结点;如上图:A
  7. 结点的层次:从根开始定义起,根为第1层,根的⼦结点为第2层,以此类推
  8. 树的⾼度或深度:树中结点的最⼤层次; 如上图:树的⾼度为4
  9. 树的以下概念只需了解,在看书时只要知道是什么意思即可:⾮终端结点或分⽀结点:度不为0的结点; 如上图:D、E、F、G…等节点为分⽀结点
  10. 兄弟结点:具有相同⽗结点的结点互称为兄弟结点; 如上图:B、C是兄弟结点
  11. 堂兄弟结点:双亲在同⼀层的结点互为堂兄弟;如上图:H、I互为兄弟结点
  12. 结点的祖先:从根到该结点所经分⽀上的所有结点;如上图:A是所有结点的祖先
  13. ⼦孙:以某结点为根的⼦树中任⼀结点都称为该结点的⼦孙。如上图:所有结点都是A的⼦孙
  14. 森林:由m(m>=0)棵互不相交的树组成的集合称为森林

二:Java中二叉树的实现

2.1定义二叉树节点类

首先,我们需要定义一个类来表示二叉树的节点。每个节点包含一个数据元素,以及指向左子节点和右子节点的引用。

classTreeNode{int data;TreeNode left;TreeNode right;TreeNode(int data){this.data = data;this.left =null;this.right =null;}}

2.2构建二叉树

接下来,我们可以编写代码来构建一棵简单的二叉树。

publicclassBinaryTreeMagic{publicstaticvoidmain(String[] args){// 创建根节点TreeNode root =newTreeNode(1);// 创建左子节点 root.left =newTreeNode(2);// 创建右子节点 root.right =newTreeNode(3);// 为左子节点创建左子节点 root.left.left =newTreeNode(4);// 为左子节点创建右子节点 root.left.right =newTreeNode(5);// 至此,一棵简单的二叉树构建完成// 1// / \// 2 3// / \// 4 5}}

2.3二叉树的遍历

遍历二叉树是对树中每个节点进行访问的过程。常见的遍历方式有三种:前序遍历、中序遍历和后序遍历。
学习⼆叉树结构,最简单的⽅式就是遍历。所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中
每个结点均做⼀次且仅做⼀次访问。访问结点所做的操作依赖于具体的应⽤问题(⽐如:打印节点内
容、节点内容加1)。 遍历是⼆叉树上最重要的操作之⼀,是⼆叉树上进⾏其它运算之基础。
在这里插入图片描述


在遍历⼆叉树时,如果没有进⾏某种约定,每个⼈都按照⾃⼰的⽅式遍历,得出的结果就⽐较混乱,
如果按照某种规则进⾏约定,则每个⼈对于同⼀棵树的遍历结果肯定是相同的。如果N代表根节点,L
代表根节点的左⼦树,R代表根节点的右⼦树,则根据遍历根节点的先后次序有以下遍历⽅式:
• NLR:前序遍历(Preorder Traversal 亦称先序遍历)⸺访问根结点—>根的左⼦树—>根的右⼦树。
• LNR:中序遍历(Inorder Traversal)⸺根的左⼦树—>根节点—>根的右⼦树。
• LRN:后序遍历(Postorder Traversal)⸺根的左⼦树—>根的右⼦树—>根节点

2.3.1前序遍历

前序遍历的顺序是先访问根节点,然后递归地访问左子树,最后递归地访问右子树。

voidpreOrderTraversal(TreeNode node){if(node!=null){System.out.print(node.data +" ");preOrderTraversal(node.left);preOrderTraversal(node.right);}}
2.3.2中序遍历

中序遍历的顺序是先递归地访问左子树,然后访问根节点,最后递归地访问右子树。

voidinOrderTraversal(TreeNode node){if(node!=null){inOrderTraversal(node.left);System.out.print(node.data +" ");inOrderTraversal(node.right);}}
2.3.3后序遍历

后序遍历的顺序是先递归地访问左子树,然后递归地访问右子树,最后访问根节点。

voidpostOrderTraversal(TreeNode node){if(node!=null){postOrderTraversal(node.left);postOrderTraversal(node.right);System.out.print(node.data +" ");}}
在这里插入图片描述
前序遍历结果:1 2 3 4 5 6
中序遍历结果:3 2 1 5 4 6
后序遍历结果:3 2 5 6 4 1
2.3.4 层序遍历

层序遍历:除了先序遍历、中序遍历、后序遍历外,还可以对⼆叉树进⾏层序遍历。设⼆叉树的根节
点所在层数为1,层序遍历就是从所在⼆叉树的根节点出发,⾸先访问第⼀层的树根节点,然后从左到
右访问第2层上的节点,接着是第三层的节点,以此类推,⾃上⽽下,⾃左⾄右逐层访问树的结点的过
程就是层序遍历。

在这里插入图片描述
以这棵树为例写下面题目:

1.某完全⼆叉树按层次输出(同⼀层从左到右)的序列为 ABCDEFGH 。该完全⼆叉树的前序序列为(A)
A: ABDHECFG
B: ABCDEFGH
C: HDBEAFCG
D: HDEBFGCA
2.⼆叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK;中序遍历:HFIEJKG.则⼆叉树根结点为(A)
A: E
B: F
C: G
D: H
3.设⼀课⼆叉树的中序遍历序列:badce,后序遍历序列:bdeca,则⼆叉树前序遍历序列为(D)
A: adbce
B: decab
C: debac
D: abcde
4.某⼆叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同⼀层从左到右)的
序列为(A)
A: FEDCBA
B: CBAFED
C: DEFCBA
D: ABCDEF

2.4完整代码示例

下面是一个包含二叉树构建和遍历功能的完整Java代码示例:

classTreeNode{int data;TreeNode left;TreeNode right;TreeNode(int data){this.data = data;this.left =null;this.right =null;}}publicclassBinaryTreeMagic{voidpreOrderTraversal(TreeNode node){if(node!=null){System.out.print(node.data +" ");preOrderTraversal(node.left);preOrderTraversal(node.right);}}voidinOrderTraversal(TreeNode node){if(node!=null){inOrderTraversal(node.left);System.out.print(node.data +" ");inOrderTraversal(node.right);}}voidpostOrderTraversal(TreeNode node){if(node!=null){postOrderTraversal(node.left);postOrderTraversal(node.right);System.out.print(node.data +" ");}}publicstaticvoidmain(String[] args){BinaryTreeMagic tree =newBinaryTreeMagic();// 创建根节点TreeNode root =newTreeNode(1);// 创建左子节点 root.left =newTreeNode(2);// 创建右子节点 root.right =newTreeNode(3);// 为左子节点创建左子节点 root.left.left =newTreeNode(4);// 为左子节点创建右子节点 root.left.right =newTreeNode(5);System.out.println("前序遍历:"); tree.preOrderTraversal(root);System.out.println();System.out.println("中序遍历:"); tree.inOrderTraversal(root);System.out.println();System.out.println("后序遍历:"); tree.postOrderTraversal(root);System.out.println();}}

三:二叉树的应用场景

  1. 搜索算法:二叉搜索树(BST)是一种特殊的二叉树,它满足左子树所有节点的值小于根节点的值,右子树所有节点的值大于根节点的值。这种特性使得在BST中进行搜索操作的时间复杂度为O(log n),大大提高了搜索效率。
  2. 表达式求值:通过构建表达式二叉树,可以方便地对数学表达式进行求值。例如,对于表达式“(3 + 4) * 2”,可以构建相应的二叉树来进行计算。
  3. 文件系统目录结构:可以用二叉树来模拟文件系统的目录结构,根节点表示根目录,子节点表示子目录或文件,方便进行文件管理和查找。

⽂件系统管理(⽬录和⽂件)

在这里插入图片描述


在这里插入图片描述

四:二叉树的重点

4.1概念

⼀棵⼆叉树是结点的⼀个有限集合,该集合:

  1. 或者为空

或者是由⼀个根节点加上两棵别称为左⼦树和右⼦树的⼆叉树组成

从上图可以看出:
1. ⼆叉树不存在度⼤于2的结点
2. ⼆叉树的⼦树有左右之分,次序不能颠倒,因此⼆叉树是有序树 注意:对于任意的⼆叉树都是由以下⼏种情况复合⽽成的:

4.2大自然的一些奇观

在这里插入图片描述


在这里插入图片描述

4.3两种特殊的⼆叉树

  1. 满⼆叉树: ⼀棵⼆叉树,如果每层的结点数都达到最⼤值,则这棵⼆叉树就是满⼆叉树。也就是
    说,如果⼀棵⼆叉树的层数为K,且结点总数是 ,则它就是满⼆叉树。

完全⼆叉树: 完全⼆叉树是效率很⾼的数据结构,完全⼆叉树是由满⼆叉树⽽引出来的。对于深度
为K的,有n个结点的⼆叉树,当且仅当其每⼀个结点都与深度为K的满⼆叉树中编号从0⾄n-1的结
点⼀ 对应时称之为完全⼆叉树。 要注意的是满⼆叉树是⼀种特殊的完全⼆叉树。

在这里插入图片描述

4.4二叉树的一些性质

1. 若规定根结点的层数为1,则⼀棵⾮空⼆叉树的第i层上最多有(i>0)个结点
2. 若规定只有根结点的⼆叉树的深度为1,则深度为K的⼆叉树的最⼤结点数是(k>=0)
3. 对任何⼀棵⼆叉树, 如果其叶结点个数为 n0, 度为2的⾮叶结点个数为 n2,则有n0=n2+1
4. 具有n个结点的完全⼆叉树的深度k为上取整
5. 对于具有n个结点的完全⼆叉树,如果按照从上⾄下从左⾄右的顺序对所有节点从0开始编号,则对
于序号为i的结点有:
◦ 若i>0,双亲序号:(i-1)/2;i=0,i为根结点编号,⽆双亲结点
◦ 若2i+1<n,左孩⼦序号:2i+1,否则⽆左孩⼦
◦ 若2i+2<n,右孩⼦序号:2i+2,否则⽆右孩⼦
下面一些题目为例:

某⼆叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该⼆叉树中的叶⼦结点数为( )
A 不存在这样的⼆叉树
B 200
C 198
D 199
答案:B
2.在具有 2n 个结点的完全⼆叉树中,叶⼦结点个数为( )
A n
B n+1
C n-1
D n/2
答案:A
3.⼀个具有767个节点的完全⼆叉树,其叶⼦节点个数为()
A 383
B 384
C 385
D 386
答案:B
4.⼀棵完全⼆叉树的节点数为531个,那么这棵树的⾼度为( )
A 11
B 10
C 8
D 12
答案:B

五:总结

Java二叉树就像代码世界里的神奇魔法棒,通过巧妙地构建和操作树形结构,为我们解决各种复杂的编程问题提供了有力的工具。无论是高效的搜索算法,还是复杂的表达式求值,二叉树都展现出了其独特的魅力和强大的功能。希望通过本文的介绍和代码示例,你能对Java二叉树有更深入的理解和认识,在编程的道路上运用这神奇的树形魔法创造出更多精彩的代码。
可以已经准备好进一步探索二叉树的更多高级特性和应用,比如平衡二叉树、红黑树等,它们将为你的编程技能库增添更多强大的武器。

Read more

sftpgo汉化处理

问题描述 官方提供的sftpgo webui的默认语言为英文, 没有待中文的语言包。实际上中文语言包已经翻译完毕,本文介绍一种在不重新编译的情况下为sftpgo的webui增加中文包的方法。 准备 1. (已完成安装的跳过) 安装sftpgo的官方安装包, 这里例子中使用的是: sftpgo_v2.6.6_windows_portable.zip 具体下载地址: https://github.com/drakkan/sftpgo/releases 2. 下载已经汉化的中文资源,其实际上是一个json文件, 可以参考这个:https://gitee.com/chenbichao/sftpgo-ryan/blob/master/static/locales/zh/translation.json 3. sftpgo服务已可以正常使用 原理 webui的前端资源都已经在sftpgo的可执行文件的同级目录下存在,分别是template文件夹下的页面展示信息 和 static文件夹下的资源。通过直接修改template中的js代码可以增加页面中的语言选项,并在用户点击是自动下

By Ne0inhk
Flutter 组件 saropa_lints 适配鸿蒙 HarmonyOS 实战:代码质量守卫,构建性能合规性检查与自定义分析规约治理架构

Flutter 组件 saropa_lints 适配鸿蒙 HarmonyOS 实战:代码质量守卫,构建性能合规性检查与自定义分析规约治理架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 saropa_lints 适配鸿蒙 HarmonyOS 实战:代码质量守卫,构建性能合规性检查与自定义分析规约治理架构 前言 在鸿蒙(OpenHarmony)生态迈向大规模工业化协同、涉及超大型项目敏捷迭代、海量模块解耦及严苛 AOT 性能交付标准的背景下,如何实现一套能够自动拦截低质量代码、保障跨团队开发风格绝对统一且符合鸿蒙性能极致要求的“静态扫描中心”,已成为决定应用长期可维护性与研发效能感的关键。在鸿蒙设备这类强调 AOT 静态优化与严格类型安全的环境下,如果应用代码中充斥着滥用的 dynamic 调用或循环引用,由于由于编译期的类型擦除与运行时的屏障开销,极易由于由于“代码腐化”导致鸿蒙应用在长期运行后发生不可预知的内存泄露。 我们需要一种能够强制约束研发纪律、支持自定义规则扩展且具备“一站式”合规性判定的 Linter 方案。 saropa_lints 为 Flutter 开发者引入了“质量铁律”范式。它不是简单的代码检查

By Ne0inhk
Flutter 三方库 objectbox_generator — 自动化构建鸿蒙极速 NoSQL 数据库映射(适配鸿蒙 HarmonyOS Next ohos)

Flutter 三方库 objectbox_generator — 自动化构建鸿蒙极速 NoSQL 数据库映射(适配鸿蒙 HarmonyOS Next ohos)

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net。 Flutter 三方库 objectbox_generator — 自动化构建鸿蒙极速 NoSQL 数据库映射(适配鸿蒙 HarmonyOS Next ohos) 在高性能移动应用开发中,本地数据的持久化存储效率往往是决定用户感知流畅度的木桶短板。传统的 SQLite 虽然结构化程度高,但在处理大规模对象关系映射(ORM)时,复杂的 SQL 拼接和反射解析往往会成为性能瓶颈。 ObjectBox 作为一个专为移动设备打造的、跨平台的超高速 NoSQL 数据库,已经成为了许多追求极致体验开发者的首选。而在 Flutter for OpenHarmony 开发中,配合 objectbox_generator,我们可以通过注解驱动的自动化流程,掌握这套高性能数据库的核心用法。 ⚠️ 鸿蒙适配现状提示:截至本文撰写时,ObjectBox 的 Dart 插件尚未提供官方的 OpenHarmony

By Ne0inhk