认识一棵二叉树

简介: 大家好,我是王有志。今天要学习的是编程中绕不开的结构--树,无论是二分搜索树,红黑树,B+树,还是的决策树和随机森林,都和树息息相关。

大家好,我是王有志,欢迎和我聊技术,聊漂泊在外的生活。

今天我们要学习的是你编程生涯中不可避免的话题--树,无论是二分搜索树,红黑树,B+树,还是机器学习中的决策树和随机森林,都和树息息相关。

认识一棵树

按照惯例,我会把的定义放上来,这次也不例外:

树是n(n≥0)个节点的有限集,当n=0时被称为空树。在任意一棵非空树中: (1)有且仅有一个特定的节点称为根(Root)节点; (2)当n>1时,其余节点可分为m(m>0)个互不相交的有限集T1,T2...Tn,其中每个集合本身也是一棵树,且称为根的子树(SubTree)。

定义看起来可能会有些晕,下面我们通过一张多叉树的图来理解树中的概念和定义:

图1:一棵多叉树.png

结合定义,相信你已经理解了大部分的概念和定义,那么我们再补充一点点关于树的度的定义。

在树中节点的度指的是节点拥有的子节点的个数,例如,节点B的度是2,节点D的度是3,而树的度指的是树中度最大的节点的度。这么说可能有些拗口,通俗点讲就是,哪个节点拥有最多的子节点,它的子节点个数就是树的度。

二叉树的分类

如果我们按照树的度进行分类,那么树只有两类:二叉树和多叉树。

图2:树的分类.png

树的度小于等于2的称为二叉树,大于2的称为多叉树。

满二叉树

对于满二叉树,国内外的定义有些许的差异:

国内定义为,一棵二叉树中,每层节点的个数都达到最大值,就是满二叉树。即深度为k的二叉树,节点个数为2k−1。

国外定义为,一棵二叉树中,非叶子节点都有两个子节点,就是满二叉树。区别在于,国内的定义要求每层节点个数都是满的。

图3:满二叉树.png

完全二叉树

对于一棵二叉树,如果将其每个节点进行从上到下,从左到右依次编号,可以与满二叉树重合,就是完全二叉树。从定义上看,完全二叉树是满二叉树的其中一类子集

图4:完全二叉树.png

可以看到,完全二叉树并不要求每个非叶子节点都有两个子节点,但是要求“有序”。

平衡二叉树

平衡二叉树是左右子树高度差不超过1的二叉树。

图5:平衡二叉树.png

如果只从结构上来看,平衡二叉树是完全二叉树。区别在于,我们在实现平衡二叉树时,会添加节点之间的排序关系,因此在构建树平衡二叉树的时候,为了保持这种平衡需要进行旋转。常见的平衡二叉树有,AVL树红黑树替罪羊树等。

斜树

当一棵树只有左/右子节点时,我们称之为左/右斜树。

图6:左斜树.png

从结构上看,我们也可以认为链表是一种斜树。

二叉树的存储结构

像栈一样,我们也可以实现顺序结构的二叉树或者链式结构的二叉树。实际上链表也是可以通过一维数组描述--静态链表,但是没有必要。

静态结构

二叉树也可以通过一维数组描述。

图7:静态结构.png

我们有一个存储了8个节点的二叉树,将根节点存储在下标为1的位置,记为index_a,我们就可以通过简单的计算获的根节点A的左右子节点的下标:

节点A的左子节点(节点B):$2×index_a=2$
节点A的右子节点(节点C):$2×index_a+1=3$

同样的我们通过计算可以访问到C的左右子节点:

节点C的左子节点(空节点):$2×index_c=6$
节点C的右子节点(节点F):$2×index_c+1=7$

但是你发现了吗?为了保证公式可用,即便节点C没有左子节点,我们也必须将位置空出来,造成了内存空间的浪费,显然是不够理想的方式。

链式结构

我们也可以创建类似双向链表节点的方式,创建二叉树的节点:

public class TreeNode<E> {
  private E element;
  private TreeNode<E> leftChild;
  private TreeNode<E> rightChild;
}

实际上,这点代码已经可以构建一棵二叉树了。

图8:链式结构.png

和链表一样,只有TreeNode在使用起来会非常麻烦,要手动实现添加,查找等功能,增加了使用难度。我们可以将功能封装起来只提供接口,不过这不是今天的重点,我们按下不表。

结语

今天我们初步认识了树中的概念和定义,希望通这张图能够让你快速的理解,而不需要死记硬背。

接着我们一起看了4种二叉树结构,这些特殊的结构也是我们学习后面二叉树何种实现的基础。

最后介绍了二叉树的两种存储结构,对于这种动态数据结构通过一维数组的实现方式,我们了解其原理就够了。

你可能会发觉今天画了很多图,是因为我们要学习的数据结构从一维升到了二维,靠想象我已经很难在脑袋中描绘出它们了。


好了,今天就到这里了,Bye~~

目录
相关文章
|
供应链
代采系统如何利用大数据分析优化采购决策?
代采系统可以利用大数据分析来优化采购决策
|
前端开发
什么是精灵图?
什么是精灵图?
422 0
|
Linux 网络安全 开发工具
Git拉取代码的完整示例操作
Git拉取代码的完整示例操作
1444 0
|
SpringCloudAlibaba 容灾 关系型数据库
nacos常见问题之启动报错如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
2524 2
|
存储 PHP 数据库
新手教程 快速部署PbootCMS到本地或者服务器
新手教程 快速部署PbootCMS到本地或者服务器
2031 0
|
4月前
|
负载均衡 Java 应用服务中间件
杂项10
Spring Cloud Alibaba 与 Spring Cloud 均基于 Spring Boot 构建微服务,遵循相同规范且组件可协同使用。区别在于,Spring Cloud Alibaba 使用 Nacos 实现服务发现与配置管理,推荐 Sentinel 作为断路器,并支持 Dubbo 与 Feign 远程调用。Nginx 可通过配置 upstream 实现负载均衡,作为反向代理,其“反向”体现在外网通过 Nginx 访问内部服务器。
|
8月前
|
搜索推荐 数据挖掘 数据安全/隐私保护
频率派与贝叶斯统计在营销组合建模中的应用比较:隐私优先时代的方法选择
营销组合建模(MMM)是量化营销渠道贡献的核心工具,在数字营销进入隐私优先时代后焕发新生。文章探讨了频率派与贝叶斯统计学在MMM中的应用,前者实现简单、结果直观,适合数据充足场景;后者能整合先验知识、量化不确定性,适应复杂和数据稀缺情况。两者各有优劣,选择需结合业务需求与数据条件。贝叶斯方法在隐私保护趋势下尤为重要,为未来营销分析提供新思路。
242 47
频率派与贝叶斯统计在营销组合建模中的应用比较:隐私优先时代的方法选择
|
Linux iOS开发 MacOS
Flask 安装
Flask 安装还是比较简单的。
516 18
ly~
|
并行计算 算法 API
SDL 图形库优化对硬件要求有何变化
SDL(Simple DirectMedia Layer)图形库是一个跨平台的多媒体库,适用于多种操作系统和设备。优化后的SDL 2.0对硬件的要求有所提升,特别是显卡性能。优化包括提高渲染效率、利用硬件加速功能、支持高效解码算法等,以增强图形处理能力和流畅度。同时,优化后的SDL对输入设备的交互体验要求更高,需确保键盘、鼠标、触摸屏等设备的顺畅操作。尽管如此,SDL仍保持良好的兼容性,能在较低配置的硬件上运行,只是性能表现会有所差异。
ly~
851 4
|
存储 C++ Python
[oeasy]python037_ print函数参数_sep分隔符_separator
本文介绍了Python中`print`函数的`sep`参数,即分隔符。通过回顾上文内容,解释了类型与`type`的概念,并强调了参数类型的重要性。文章详细探讨了`print`函数如何使用`sep`参数来分隔输出值,默认分隔符为空格(序号32)。还讨论了如何修改分隔符为其他字符,如冒号,并解释了为何反斜杠需要使用双反斜杠表示。最后,文章追溯了`sep`名称的由来,以及相关词汇的历史背景,如盎格鲁-萨克逊人的武器和语言。
417 1