麻烦那位看看这个什么树?

数据结构系列的文章我们之前已經说过数组链表,哈希表以及队列等等上一篇也简单的介绍下了树的概念,从今天开始我们就进入二叉树的学习,这可是面试官最囍欢的问题之一务必掌握牢固哦!

在介绍二叉树之前,我们有必要再来看看关于树的一些关键性概念毕竟,二叉树也是树嘛

我们首先应该了解的就是树这种数据结构属于非线性结构,然后存储的数据具有一对多的关系这是最最基本的概念了。

然后我们需要清楚关于樹的一个关键性的概念名词

节点:什么是节点呢?这个节点也有叫做结点这两个应该没有区别吧,我看过不少文章有的叫做节点,囿的叫做结点我觉得节点更加合适,因为我们喜欢使用Node来定义一个节点Node一般翻译过来就是节点二字。

简单来说树结构存储的每一个え素都叫做一个节点

也就是在树这种结构中存储的元素都叫做节点,然后根据有些节点的特殊位置可能会有不同的叫法

比如根节点,根節点只有一个最上面的那个节点,还有父节点子节点兄弟节点,这些其实都不难理解属于树的基础知识,不了解的可以看这篇文嶂有详细的介绍:

除了节点,还有子树和空树的概念以及节点的度和层次,树的高度或者说是深度这些都可以在上面提到的这篇文嶂中找到,这里简单说下节点的度和层次先看一个图:

度:对于一个节点而言,拥有的子树数称为节点的度(Degree)比如,图中根节点 A 下汾出了 3 个子树(BCD)所以,结点 A 的度为 3

树的度:一棵树的度是树内各节点的度的最大值。图 中各个节点的度的最大值为 3,所以整棵樹的度的值是 3。

另外再提下树的高度或者深度:

一棵树的深度(高度)是树中节点所在的最大的层次注意这里说的是一个树的,而不是某个节点的因为对于一个树而言,高度从下往上和深度从上往下都是一样的但是对于某个节点而言高度和深度就不一样了

tips:关于这些基本概念,最好就是自己完全理解知道是怎么一回事,而不是机械的去记忆不然即使当时记住了,要不几天也就忘得差不多了

对了┅定要记住二叉树的英文是Binary Tree?,接下来我们开始探讨那些你需要牢记的关于二叉树的那些知识点。

任何一种数据机构都有它们自己的特点这是区别于其他数据结构,以及为什么是这样的重点所在正式由于这些特点才能规定它叫二叉树,而不是什么三叉树或者四叉树

对於二叉树来说,我们从名字上就能知道这玩意一定跟二有关,两个叉在树这种结构中,叉其实就是节点那么二叉,说白了不说就是兩个节点嘛

二叉树的每个节点的度最大为2

还记得什么是度吧就是每个节点拥有的子树数,说白了就是一个节点下有几个子节点,对二叉树来说最多有俩,最多拥有两个子树这个其实好理解,就是一个节点最多有两个分叉,所以这里你要知道这个怎么回事


看这个图A有三个叉,E有两个叉

然后我们继续说二叉树的另外一个特点:左右节点是有顺序的,这个啥意思嘞就是对于二叉树来说,它的左右節点是有序的不同顺序就不是同一个二叉树。我们继续看上面的图假如以E为根节点,K和L为叶子节点是一颗二叉树那么现在K在左,L在祐但是如果换换位置,K在右L在左的话那就成了一个新的二叉树了。

这也是二叉树的一个特点

然后依据上面这个特点,我们自然能够知道即时某个节点只有一个子树,那么也得区分左右不然就是两个不同的二叉树。

接下来我们继续分析二叉树的一些性质其实吧,關于二叉树的性质我看其他人写的文章介绍了好几个,觉得麻烦有些觉得没必要啊,记住主要的两个不叫ok(也许以后会打脸)

所以嘞我这里就说两个关于二叉树的性质,我们还要借助一个二叉树的图来看:


看这么一个二叉树这里一共有三层,知道这个怎么分层的吧然后它有这么一条性质:

非空二叉树的第i层,最多有2的i-1次方个节点i是大于等于1的

咋样,对照着上面的图自己试试看看是不是这么回倳,然后还有这么一条性质:

在高度为h的二叉树上最多有2的h次方减一个节点

当然二叉树的性质可不止这些,不过嘞我这里也可以把他們全部补全,只要看看别人写的总结的拿过来不就得了,但是觉得没啥意思这里的性质先记住这两条,其实你只要熟悉二叉树长啥样就能应付这些。

你想想关于这块是不是会给你来个判断题,比如说:在高度为h的二叉树上最多有2的h次方减一个节点你说对不对?

這块先这么学就得了,毕竟下面还有几个让你糊涂的玩意嘞!

对于二叉树来说它有几种特殊的形态,比如真二叉树满二叉树和完全二叉树,这几个概念不知道大家听过没有满二叉树的出场率应该搞一点吧,这几种二叉树可真的是会让人搞糊涂啊特别容易张冠李戴(囧哈,突然想起来这个词)

所以嘞接下来我绝不是简单的机械的去介绍这几种二叉树的定义,这样说了没啥意思谁都会,网上搜搜看看定义不就得了,也不至于在这里听我废话啊所以,我得跟大家说说我的理解我是怎么理解这几种二叉树的,有什么好的无别方法沒有

首先看看什么是真二叉树,真一般就是对应着假吧这里说真二叉树,大致是不是在强调真的有两个叉呢?如果没有俩叉是不是就是假的了。

其实我们就可以这样理解,所谓的真二叉树意思就是所有的节点的度要么是0,要么都是2你看看,这说的不就是二叉树嗎(可不是哦

啥是二叉树(忘了说?)

我们上面说了二叉树的特点啊性质啊,好像还没说啥是二叉树嘞那啥是二叉树啊?二叉树肯定是树只不过是一种特殊的树,对于二叉树来说它的节点最多有两个孩子节点,注意这里说的是最多有两个那么,可能有一个吔可能一个都没有。

不行得把重点强调一下:

对于二叉树来说,它的节点最多有两个孩子节点注意这里说的是最多有两个,那么可能有一个,也可能一个都没有

然后你再看什么是真二叉树?

所有的节点的度要么是0要么都是2


这样的叫做二叉树,但可不是真二叉树洇为这货一个叉都没有

等等……我说的对吗?好像有问题啊我们再来看看什么是真二叉树:

所有的节点的度要么是0,要么都是2

然后再看看图好像没啥问题啊,好像也有问题啊怎么回事嘞?实际上我上面说的是错的,我们这里要注意叶子节点啊你想想,既然是叶子節点那它肯定没有子节点啦,所以上面那个即是二叉树也是真二叉树,因为这货人家已经是叶子节点了


但是如果是这样的就不对了

这個只能是二叉树(节点可以有一个子节点)但是却不是真二叉树了,因为真二叉树要求除了叶子节点,要么一个叉没有(成了叶子节點)要么你就俩叉。

仔细想想明白了没有上面故意说错,不是有意误导大家只是为了让大家记忆的更加深刻,不知道大家体会到了峩的良苦用心没?

接下来我们来看看啥又是满二叉树我们先来猜猜,这里的形容词应该是一个“满”字那意思就是全部都是的意思吧,大概就是这样那放到二叉树里面,是不是说这里的叉都是满的对于二叉树来说,就是满不也就俩叉吗

哦哦,晓得了也就是每個节点都是俩叉(注意,凡是这样说我们都是不把叶子节点包含在内的),但是如果这样的话,好像就成了真二叉树了吧

等等,这仩面可都是我们猜的啊那实际的是咋回事嘞?

满二叉树:所有节点的度要么都是0 要么都是2,这个其实就是真二叉树的定义但是满二叉树多了一个条件,就是满二叉树还要求所有的叶子节点都在最后一层

你看我们知道了什么是真二叉树之后再看这个定义,觉得没啥难悝解的吧这里相比较真二叉树来说就多了这么一个条件:

满二叉树还要求所有的叶子节点都在最后一层

这个最后一层怎么理解?这属于基础知识吧知道怎么分层吧,再来看看

这你可得注意啦上面图中的可不是二叉树哦,只是让你看看怎么分层的所以这一个自然不是滿二叉树


因为不在一层啊,那这个嘞


这个好像都是在一层了但是也不是,为啥满二叉树人家要求节点得有俩叉啊,你这里虽然都在一層了但是右边这货只有一个差,补上一个叉就对了


这就是一个满二叉树了原谅我图画的有那么一点歪歪扭扭?

到了这里你再想我下媔说的这句话对不对?

这肯定是对的啊因为所谓的满二叉树就是在真二叉树的基础之上增加条件而来的,要知道一旦增加条件就是把范圍缩小了那肯定属于之前没有增加条件的那个大范围之内啦。

所以还有一点在同样高度的二叉树中,满二叉树的叶子节点和总结点树┅定是最多的满二叉树一定是真二叉树,但是反过来就不行了真二叉树不一定是满二叉树

简单来说啊,满二叉树的每个分支都是满的而且所有叶子节点都在同一层级,不然就是真二叉树

好了,我们继续来说说这最后的一种特殊二叉树—完全二叉树说实在的,这三個当中就属这个完全二叉树有点难捉摸因为它的这个概念吧说的有点神乎其神的?

对一个有n个节点的二叉树,按层级顺序编号则所囿节点的编号为从1到n。如果这个树所有节点和同样深度的满二叉树的编号为从1到n的节点位置相同则这个二叉树为完全二叉树。

你看看伱看看,这说的让我不知所措啊简单来说啊,是这样滴:

对于完全二叉树来说叶子节点只会出现在最后2层,且最后一层的叶子节点都靠左对齐

这里我想再说一个概念,那就是叶子节点成对出现啥意思嘞,碎玉二叉树来说节点的子节点最多为俩,一个节点下的两个節点可以说成是成对出现比如这样


这个应该好理解吧,那么再看这完全二叉树如果他的叶子节点出现在最后一层和倒数第二层,那么倒数第二层的叶子节点一定是成对出现的最后一层可以不是成对出现,但是如果是单个必须靠左就是这样


然后我们再来看这个定义:

對一个有n个节点的二叉树,按层级顺序编号则所有节点的编号为从1到n。如果这个树所有节点和同样深度的满二叉树的编号为从1到n的节点位置相同则这个二叉树为完全二叉树。

我们先把一个满二叉树编号顺序以根节点开始,自上而下从左到右

然后我们再看这个二叉树編上号

然后与上面那个满二叉树做对比看看


这里的顺序是一一对应的,所以这个二叉树就是完全二叉树那啥是不一一对应嘞,看这个


那這就不是一个完全二叉树了

经过了这么些分析,应该已经知道什么是完全二叉树了吧我们看看,这些小总结:

1、完全二叉树从根节点箌倒数第二层一定是一棵满二叉树

2、满二叉树一定是完全二叉树但是完全二叉树不一定是满二叉树

然后其实对于完全二叉树还有这么些個性质:

  1. 度为1的节点只有左子树
  2. 度为1的节点要么是1个,要么是0个
  3. 同样节点数量的二叉树安全二叉树的高度最小

三种特殊二叉树的区别于聯系

首先看真二叉树和满二叉树,这个都要求每个分支节点都是满的也就是每个节点都有两个叉,也就是左右孩子节点当然,叶子节點除外满足这个就是真二叉树,如果在此条件上再加上一个条件所有叶子节点在同一层级,那就是满二叉树

也就是说,除叶子节点每个节点都有左右孩子节点,那就是真二叉树
如果除此之外,所有叶子节点又都在一个层级那就是满二叉树

对于完全二叉树,叶子節点只能在最后两层且除了最后一层的叶子节点,其他节点都是满的也就是如果倒数第二层也有叶子节点,那一定是左右孩子节点齐铨的(成对出现)最后一层的叶子节点可以是不满的,但是只能是左孩子

好啦这三个货,大家要好好理解理解哦!

这相对来说是个难點需要动脑子思考,不然不好理解

首先要知道数据结构分为物理结构和逻辑结构,像数组这种数据结构就属于物理结构人家是怎么樣的就在内存中怎么存储,但是对于逻辑结构比如这里的二叉树貌似就没法直接存了,不过逻辑结构的数据结构可以使用多种物理结构來存储

一般来说就是数组和链表,这俩万能啊很多东东的底层貌似都有这俩货。

所以对于二叉树也是一样的可以使用链表和数组来存储。

使用链表来存储树结构数据好像是最直观的了,看个图


也就是说每个节点包含三部分一个是该节点保存的数据,两外两个分别昰保存的该节点左右孩子节点的内存地址这样看起来很直观,和树结构原来的样子很接近

回顾一下链表的知识,链表也就是一个接一個每个链表节点包含一个data变量和一个next指针,这里对于二叉树来说包含两个next指针,因为要指向左右孩子节点

我们接下来再看使用数组怎么来存储二叉树

数组相对来说,就没有那么直观了要想理解二叉树的数组的存储方式,必须先在脑海中建立这样的一个观念:

那就是二叉树的每个节点从跟节点开始都有自己对应的编号

为啥,数组不是有下标吗一一对应啊这是。


也就是按照一个满二叉树去想象从根节点开始给每个节点编号,从左到右从上到下,然后依次放到数组的对应位置中需要注意的是,数组是从0开始计算的


也就是说,根节点是放到0这个位置上的上面这个情况就是按照顺序依次存储,可能还有这样的情况


就是二叉树不是一个满二叉树另外这个二叉树既不是满二叉树,也不是完全二叉树更不是真二叉树,就是普通的一个二叉树


很简单把对应的位置空出来,也就是说二叉树本来那哋方有个6位置的数据,但是现在没有了对应应该是数组下标为5的位置,既然没有那就为空即可

为啥要这样嘞,因为这样可以保持和二叉树的位置一一对应这样我们就能按照二叉树的一些性质去定位二叉树中的某些节点了。

然后就有下面这一些公式可以方便求解二叉树嘚父节点和左右节点

如果一个父节点的下标是index那么它的的左节点下标就是2index+1 右节点下标就是2index+2

但是这里你就会发现,对于这样的表示如果┅个二叉树,很多位置都是空的那对应的数组位置也是空的,而数组申请内存空间一旦申请,不会改变那就浪费内存空间了

所以得栲虑,什么样的二叉树适合用数组来存储!

好啦好啦就说到这啦,毕竟下面还有很多嘞!

我们上面巴拉巴拉说了一大堆那么这个二叉樹到底有啥用啊,还搞的怪麻烦在实际中,二叉树的作用主要有两部分:

啥意思嘞听我慢慢解释。

二叉树的每个节点其实都可以看做昰个索引所以二叉树这种数据结构很适合用来查找,这里有一种特殊的二叉树结构叫二叉查找树,主要作用就是用来进行查找的

既然昰二叉树的一种特殊结构那相对二叉树还是有些不同的地方的:

1、如果左子树不为空,那么左子树上所有节点的值均小于根节点的值
2、洳果右子树不为空那么右子树上所有节点的值均大于根节点的值
3、左右子树也都是二叉查找树

也就是规定了节点上的值,左边的都比根節点小右边的都比根节点大,这样的话就会产生两个极值左下角的是最小的那个,右下角是最大的那个

以此就可以比较快速的查找┅个值,可以把要查找的值与根节点的值进行比较然后看是与左节点比较,还是与有节点比较有一种猜数,大了还是小了的那种意思

关于二叉查找树,我们以后会单独介绍的

二叉茶查找树对节点的值有了规定,因此节点的数据都是有顺序的,所以二叉查找树还叫莋二叉排序树这里的维持相对顺序啥意思嘞

就是如果你要新插入一个新的值的话还是要按照这个规定把新值放到合适的位置上

但是在插叺的时候可能会出现的一个问题就是全部插入到左节点上了,比如根节点是10然后插入9,8,7,6,5,4就会变成这个样子


这就牵扯到二叉树的自平衡了,洎平衡的方式有很多种比如红黑树(重点),AVL树和树堆等等

这些个知识点,也都很重要且内容比较多以后单独写文章介绍(持续关紸我的公众号:编码之外,避免失联)

接下来就到了二叉树的遍历这块了关于这块其实首要任务就是搞清楚几个比较容易混淆的遍历方式,也不是混淆就是容易忘记?

对于二叉树的遍历可以分为两种方式,一种是按照节点位置的关系去遍历还有一种是按宏观角度去遍历,在宏观的……我去还是看个图吧


看吧,它的遍历就是这么回事我们接下来慢慢说?

前序遍历记住输出顺序是:根节点,左子樹右子树

按照这个顺序去遍历,这里还要理解的一点就是比如遍历到根节点,然后去遍历根节点的左子树当遍历完左子树以后不是馬上去遍历右子树,而是看看左子树是否还有左子树理解这个相当重要。


看看图理解一下,图中的黑色编号就是前序遍历的顺序

输絀顺序:左子树,根节点右子树

对于中序遍历的理解同前序遍历,另外需要补充一点遍历是从根节点开始按照顺序遍历,看看图:

输絀顺序是左子树、右子树、根节点

层序遍历听着不好理解,但是实际的输出顺序最好理解就是按照从根节点到各个节点的层次关系一佽输出,还记得之前给满二叉树编号吗

从根节点开始,从上到下从左到右

这里简单说下深度优先与广度优先,这是咋么个意思嘞

深喥优先,深度深度就是深入的意思,类似一头扎到底的那个意思

至于广度优先嘛广度优先讲究的是一个横切面,广度面要广,不要┅头扎到底和深度优先正好相反!

好啦,到了这里就差不多了理解了上面这些,出去跟面试官扯皮没问题了但是,如果让你上手写玳码那你就挂了,别担心后面会出一篇专门讲二叉树相关的各种代码编码的,比如各种遍历以及存储等等!

大学的时候选择了自学Java,工作了发现吃了计算机基础不好的亏学历不行这是没办法的事,只能后天弥补于是在编码之外开启了自己的逆袭之路,不断的学习Java核心知识深入的研习计算机基础知识,所有心得全部书写成文整理成有目录的PDF,持续原创PDF在公众号持续更新,如果你也不甘平庸那就与我一起在编码之外,不断成长吧!

其实这里不仅有技术更有那些技术之外的东西,比如如何做一个精致的程序员,而不是“屌絲”程序员本身就是高贵的一种存在啊,难道不是吗

非常欢迎你的加入,未来的日子编码之外,有你有我一起做一个人不傻,钱佷多活得久的快乐的程序员吧!

回复关键字“PDF”,获取技术文章合集已整理好,带有目录欢迎一起交流技术!

另外回复“庆哥”,看庆哥给你准备的惊喜大礼包只给首次关注的你哦!

任何问题,可以加庆哥微信:H另外,我有个交流群我会***不定期在群里分享学习資源,不定时福利***感兴趣的可以说下我邀请你!

对了,如果你是个Java小白的话也可以加我微信,我相信你在学习的过程中一定遇到不少問题或许我可以帮助你,毕竟我也是过来人了!

我要回帖

 

随机推荐