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

发布于:2025-02-24 ⋅ 阅读:(11) ⋅ 点赞:(0)

在这里插入图片描述

我的个人主页
我的专栏人工智能领域、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定义二叉树节点类

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

class TreeNode {
    int data;
    TreeNode left;
    TreeNode right;

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

2.2构建二叉树

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

public class BinaryTreeMagic {
    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);

        // 至此,一棵简单的二叉树构建完成
        //       1
        //      / \
        //     2   3
        //    / \
        //   4   5
    }
}

2.3二叉树的遍历

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

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

2.3.1前序遍历

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

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

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

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

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

void postOrderTraversal(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代码示例:

class TreeNode {
    int data;
    TreeNode left;
    TreeNode right;

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

public class BinaryTreeMagic {

    void preOrderTraversal(TreeNode node) {
        if (node!= null) {
            System.out.print(node.data + " ");
            preOrderTraversal(node.left);
            preOrderTraversal(node.right);
        }
    }

    void inOrderTraversal(TreeNode node) {
        if (node!= null) {
            inOrderTraversal(node.left);
            System.out.print(node.data + " ");
            inOrderTraversal(node.right);
        }
    }

    void postOrderTraversal(TreeNode node) {
        if (node!= null) {
            postOrderTraversal(node.left);
            postOrderTraversal(node.right);
            System.out.print(node.data + " ");
        }
    }

    public static void main(String[] args) {
        BinaryTreeMagic tree = new BinaryTreeMagic();
        // 创建根节点
        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);

        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. ⽂件系统管理(⽬录和⽂件)
    在这里插入图片描述
    在这里插入图片描述

四:二叉树的重点

4.1概念

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

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

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

4.2大自然的一些奇观

在这里插入图片描述
在这里插入图片描述

4.3两种特殊的⼆叉树

  1. 满⼆叉树: ⼀棵⼆叉树,如果每层的结点数都达到最⼤值,则这棵⼆叉树就是满⼆叉树。也就是
    说,如果⼀棵⼆叉树的层数为K,且结点总数是 ,则它就是满⼆叉树。
  2. 完全⼆叉树: 完全⼆叉树是效率很⾼的数据结构,完全⼆叉树是由满⼆叉树⽽引出来的。对于深度
    为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,否则⽆右孩⼦

下面一些题目为例:

  1. 某⼆叉树共有 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二叉树有更深入的理解和认识,在编程的道路上运用这神奇的树形魔法创造出更多精彩的代码。
可以已经准备好进一步探索二叉树的更多高级特性和应用,比如平衡二叉树、红黑树等,它们将为你的编程技能库增添更多强大的武器。


网站公告

今日签到

点亮在社区的每一天
去签到