二叉树

作者: 我要离开浪浪山 | 来源:发表于2023-03-26 22:58 被阅读0次

一、前言:

日常生活中,很多事物都可以用树来描述,例如书的目录、工作单位的组织架构等等。树是计算机中非常重要的一种数据结构,树存储方式可以提高数据的存储、读取效率。

1、二叉树的定义

  • 二叉树是一种树形数据结构,其每个节点最多有两个子节点,称为左子节点和右子节点。
  • 左子节点始终位于父节点左侧,右子节点始终位于父节点右侧。
  • 二叉树经常被用来存储和操作数据,例如在搜索算法和排序算法中使用。

满足以下两个条件的树就是二叉树:
- 本身是有序树;
- 树中包含的各个节点的度不能超过 2,即只能是 0、1 或者 2;

2、树的基本定义

日常生活中,很多事物都可以用树来描述,树是计算机中非常重要的一种数据结构,树存储方式可以提高数据的存储、读取效率,比如利用二叉排序树,既可以保证数据的检索速度,同时,也可以保证数据的插入、删除、修改的速度。

v2-ec4ba2c73bcf7dfe03fa5d26b9164afd_r.jpg

其实,树的种类有很多种,比如普通的二叉树、完全二叉树、满二叉树、线索二叉树、哈夫曼树、二叉排序树、平衡二叉树、AVL平衡二叉树、红黑树、B树、B+树、堆等。今天介绍的主要内容是二叉树的基本知识和几种基础类型的二叉树。

二、二叉树的相关术语

在正式开讲前,首先介绍一些关于二叉树的专业名词和术语,包括结点、结点的度、叶子结点、分支结点、结点的层次、树的度、树的深度等,了解这些基础的专业名词和术语对于我们理解二叉树的特性有非常重要的帮助作用。

1)结点:包含一个数据元素及若干指向子树分支的信息。

2)结点的度:一个结点拥有子树的数据成为结点的度。

3)叶子结点:也称为终端结点,没有子树的结点或者度为零的结点。

4)分支结点:也称为非终端结点,度不为零的结点成为非终端结点。

5)结点的层次:从根结点开始,根结点的层次为1,根的直接后继层次为2,以此类推。

6)树的度:树中所有结点的度的最大值。

7)树的深度:树中结点的最大层次。

1、树的特点

树作为一种特殊的数据结构,有非常多的特性,比如:

1)每个结点有多个或者零个子结点
2)没有父结点的结点成为根结点,没有子结点的结点成为叶结点
3)每一个非根结点只有一个父结点
4)每个结点及其后代结点整体上可以看做是一棵树,称为当前结点为根的子树

2、二叉树的基本定义

1)二叉树就是度不超过2的树,其每个结点最多有两个子结点
2)二叉树的结点分为左结点和右结点

v2-3a2c85e3f225b34c468c127d994df3dc_r.jpg

3、满二叉树

1)二叉树的每一层的结点度都达到最大值,则这个二叉树就是满二叉树
2)一棵深度为n的满二叉树,有2^n-1个结点

v2-3dcf309dc35dd901a23ba733fbb8a84b_r.jpg

4、完全二叉树

叶子结点只能出现在最下层和次下层,最后一层的叶子结点在左边连续,倒数第二层的叶子结点在右边连续,我们称为完全二叉树。

v2-b20609703560deea765d1dddc32df2b9_r.jpg

三、二叉树的创建

接下来,我们通过代码来描述二叉树,语言以Java为例,其中结点类定义如下:

v2-da4502cca5ebe1d5867c747dcceb265c_r.jpg

二叉查找树类定义如下:


v2-30365a95f0fa9a0a5a42cd9866fab6b4_r.jpg

相关类定义好后,我们来看具体的方法实现,下面分别介绍。

1、size()方法

size()方法相对简单,每次添加元素加一,删除元素减一,维护一个公共的变量 num 即可,代码实现如下:


v2-c368cfa0f47ed20df62bce23051634b8_720w.png

2、put(Key key,Value value)方法

put(Key key,Value value)方法可以利用重载方法 put(Node x,Key key,Value value),因此实现也相对简单,其中第一个参数只需要传根结点即可,代码实现如下:

v2-be8704e88737247f3d6c089ea6d7e44b_r.png

3、 put(Node x,Key key,Value value)方法

put(Node x,Key key,Value value)方法应该是整个类中实现相对较为复杂的,下面进行简单的分析。

第一种情况,当前树中没有任何一个结点,直接将新插入的结点作为根结点。

v2-d1b22736b1fb2a794a3873b40cdc693f_r.jpg

第二种情况,当前树不为空,则从根结点开始。这种情况有可以细分为三种情况:

1)如果新结点的key小于当前结点的key,则继续查找当前结点的左子结点。

v2-6591d41281c8b68143e75de846f6078f_r.png

2)如果新结点的key大于当前结点的key,则继续查找当前结点的右子结点。

v2-79633ffdfdba88e55dc46599c8924d62_r.jpg

3)如果新结点的key等于当前结点的key,则树中已经存在这样的结点,替换该结点的value值即可。

v2-c4d43e874997b435be055de3f057c761_r.jpg

具体的代码实现如下:


v2-f3cc169545604842f3bf6fbd9bd512f3_r.jpg

4、get(Key key)方法

get(Key key)方法和 put(Key key,Value value)方法类似,也可以利用重载方法 get(Node x,Key key)来实现,代码实现如下:

v2-3f0f3502ac7865acd2e6c8d5bb09be7b_r.png

5、get(Node x,Key key)方法

get(Node x,Key key)方法实现查询方法从根结点开始,如果要查询的key小于当前结点的key,则继续找当前结点的左子结点;如果要查找的key大于当前结点的key,则继续找当前结点的右子结点;如果要查找的key等于当前结点的key,则返回当前结点的value。

具体的代码实现如下:


v2-d67f5e0c8bb4c18c13c8823bb975b10d_r.jpg

通过上面的代码,我们可以看出 get()方法和 put()方法类似,都是通过递归调用实现的。

6、delete(Key key)方法

delete(Key key)方法也是一样的思路,调用后面的重载方法就行了,代码实现如下:

v2-3c501f65ba6e2b4859e3fe9d97dfe8d7_r.png

7、delete(Node x,Key key)方法

删除方法的实现思路,以最复杂的情况为例,首先找到被删除的结点,找到被删除结点右子树中的最小结点 minNode,删除右子树中的最小结点,让被删除结点的左子树成为最小结点 minNode 的左子树,让被删除结点右子树成为最小结点minNode的右子树,让被删除结点的父结点指向最小结点 minNode。

具体的代码实现如下:


v2-5d00f8d3b02fb30af3e41a5b35c103ad_r.jpg
v2-54e8d1665025b1f30e59f18b34c22f5c_r.jpg

既然代码已经写完了,接下来通过代码来验证一下,看看我们写得是否正确:

v2-742f52aab6786110c2f645d3dbc5f32e_r.jpg

答案输出:

3
李四
2

Nice,太好了,通过上述输出结果已经证明了程序是正确的。

四、查找二叉树中最小和最大的键

比如二叉树中用来记录某个公司员工薪资和员工姓名数据,或者某班级学生们的排名和姓名数据。如何快速找出排名最高和最低的同学数据?

这样的话,该怎么做呢?其实,一般还可以整理出如下四个方法,定义如下:

v2-1d448dc3f38388070452d02bddf7ee74_r.jpg

1、min()方法

min()方法和上面提到的 get()和 put()方法类似,也可以使用下面的重载方法实现,具体代码如下:

// 找出树中最小的键
public key min() {
    return min(root).key;
}

2、min(Node x)方法

min(Node x)方法需要根据传入的结点位置,查找左子树中的最小的结点,如果为空,则直接返回空,具体代码实现如下:

// 找出树中最小键所在的结点
public Node min(Node x) {
    if (x == null) {
        return x;
    }
    Node minNode = x;
    while (minNode.left != null) {
        minNode = minNode.left;
    }
    return minNode;
}

3、max()方法

max()方法和上面提到的 min()方法类似,也可以使用下面的重载方法实现,具体代码如下:

// 找出树中最小的键
public key max() {
    return max(root).key;
}

4、max(Node x)方法

max(Node x)方法需要根据传入的结点位置,查找右子树中的最大的结点,如果为空,则直接返回空,具体代码实现如下:

// 找出树中最大键所在的结点
public Node min(Node x) {
    if (x == null) {
        return x;
    }
    Node maxNode = x;
    while (maxNode.right != null) {
        maxNode = maxNode.right;
    }
    return maxNode;
}

五、二叉树的遍历

二叉树的遍历有三种方式,分别是前序遍历、中序遍历、后序遍历。

1. 前序遍历

先访问根结点,再访问左子树,最后访问右子树,比如下图中的二叉树,前序遍历结果如下:

EBADCGFH。

2. 中序遍历

先访问左子树,再访问根结点,最后访问右子树,比如下图中的二叉树,中序遍历结果如下:

ABCDEFGH。

3. 后序遍历

先访问左子树,再访问右子树,最后访问根结点,比如下图中的二叉树,后序遍历结果如下:

ACDBFHGE。

v2-6a8b6d005d57580730cc531062e64618_r.jpg

参考:https://zhuanlan.zhihu.com/p/413522605

相关文章

  • 数据结构与算法-二叉树02

    二叉树的定义 二叉树的特点 二叉树的五中基本形态 其他二叉树 斜二叉树 满二叉树 完全二叉树图片.png满二叉树一...

  • 二叉树

    二叉树 高度 深度真二叉树 满二叉树 完全二叉树 二叉树遍历前序 中序 后序层序遍历 翻转二叉树 递归法...

  • 二叉树 基础操作

    二叉树的使用 二叉树结构 先序创建二叉树 DFS 先序遍历二叉树 中序遍历二叉树 后序遍历二叉树 BFS 层次遍历...

  • 树与二叉树

    **树 ** 二叉树 满二叉树 完全二叉树 三种遍历方法 树与二叉树的区别 二叉查找树 平衡二叉树 红黑二叉树

  • 二叉树的宽度优先搜索(层次遍历,BFS)

    二叉树结构: 二叉树宽度优先搜索: 按照二叉树的层数依次从左到右访问二叉树的节点;例如:给定一个二叉树: 按照宽度...

  • 剑指 offer:39、平衡二叉树

    39. 平衡二叉树 题目描述 输入一棵二叉树,判断该二叉树是否是平衡二叉树。 解题思路: 平衡二叉树:Wiki:在...

  • Algorithm小白入门 -- 二叉树

    二叉树二叉树构造二叉树寻找重复子树 1. 二叉树 基本二叉树节点如下: 很多经典算法,比如回溯、动态规划、分治算法...

  • 14-树&二叉树&真二叉树&满二叉树

    一、树 二、二叉树 三、真二叉树 四、满二叉树

  • 二叉树的应用

    完美二叉树(满二叉树) 除了最下一层的节点外,每层节点都有两个子节点的二叉树为满二叉树 完全二叉树 除二叉树最后一...

  • 12.树Tree(2)

    目录:1.二叉树的基本概念2.二叉树的性质3.二叉树的创建4.二叉树的遍历 1.二叉树的基本概念 2.二叉树的性质...

网友评论

      本文标题:二叉树

      本文链接:https://www.haomeiwen.com/subject/rpeardtx.html