图解二叉树、满二叉树、完全二叉树、平衡二叉树

1,468 阅读5分钟

这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战

欢迎关注公众号OpenCoder,来和我做朋友吧~❤😘😁🐱‍🐉👀

一、什么是树?

是一种数据结构,它是由n(n≥1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

每个节点有零个或多个子节点;没有父节点的节点称为根节点;每一个非根节点有且只有一个父节点;除了根节点外,每个子节点可以分为多个不相交的子树。

image-20211119120429089

如上图,许多逻辑可能存在着一对多或者对多的情况。四川省包含了很多个城市,每个城市又包含了很多个区县。

我们可以使用以上结构来保存数据同时描述所属关系,这样的非线性结构被称为树。

树是n个节点的有限集(n>=0)。当n=0时,称为空树。在任意一个非空树中,有如下的特点。

  1. 没有父节点的节点被称为根节点,且一棵树形结构中,有且仅有一个根节点。
  2. 当n>1时,其余节点可分为m(m>0)个互不相交的有限集,每一个集合本身又是一个树,并成为根的子树。

如下图所示,根、子树、叶子节点组成的树形结构。

树的专用术语,如下图:

image-20211119145423662

如上图所示,节点1的上一级节点,被称为1的父节点。从节点1衍生出来的节点被称为1的孩子节点。和节点1同级别的节点被称为1的兄弟节点。树的最大层级数,被称为树的高度。上面图上的树,高度为4。

二、什么是二叉树

二叉树是树形结构中的一种特殊形式。何为二叉?此树形结构中,每个节点最多有两个孩子节点

二叉树中节点也可能是没有子节点或者一个子节点,但不能超过两个子节点,如下图就是一颗二叉树。

image-20211119150348208

二叉树那个,节点的两个孩子节点,左边的被称为左孩子,右边的被称为右孩子。

满二叉树: 一个二叉树所有的非叶子节点都存在左右两个孩子,并且所有叶子节点都在同一层级上,这样的树被称为满二叉树。

如图:

image-20211119150930382

发现树每个非叶子节点(1、 2、 3)的,都有两个子节点,并且所有的叶子节点(4、5、6、7)都在同一个层级。

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

如图所示:

image-20211119151904321

完全二叉树的特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。需要注意的是,满二叉树肯定是完全二叉树,而完全二叉树不一定是满二叉树。

完全二叉树的条件比满二叉树要轻松一些,满二叉树要求所有的叶子节点都是满的,而完全二叉树只需要保证最后一个节点之前的节点齐全即可。

三、二叉树的应用

二叉树表现形式有多种,满二叉树和完全二叉树只是其中的两种。每一种形式都有其具体应用场景。观察所有的形式发现,二叉树最主要的还是应用于查询顺序保存两个方面。

3.1 二叉树查询

下面以二叉查找树为例,这种树主要是方便我们做查询。

二叉查找树: 在二叉树的基础上增加了以下条件:

3.1.1 如果当前节点的左子树不为空,则左子树上所有的节点的值均小于当前节点的值。

3.1.2 如果当前节点的右子树不为空,则右子树上的所有节点的值均大于当前节点的值。

3.1.3 左右子树也都满足上述两个条件。

如下图:

image-20211119153212044

以上的存储数据的条件,注定了让二叉查找树的查询更加方便。以上图为例,我们要查询 5的节点步骤如下:

1.访问根节点6,发现5<6,我们要找的5在根节点的左孩子树中。

image-20211119153908599

2.访问根节点的左孩子4,发现5>4,我们要找的5在节点4的右孩子中。

image-20211119153957256

3.访问节点4的右孩子,发现5=5,这就是我们要找的节点5。

image-20211119154045340

上述图示中,完整的表示了二叉查找树的查询思路。

如果一个节点分布相对均匀的二叉查找树,假设节点总个数为n,那查询对应节点的时间复杂度就是O(logn),和树的深度是一致的。

这样比较大小决定左右的查询方式,与二分查找算法非常接近。

3.2 二叉树顺序存储

在二叉查找树中,左子树小于父节点,右子树大于父节点,因此保证了二叉树的顺序。所以二叉查找树又被称为二叉排序树。

在新增数据的时候,仍要遵循二叉查找树的基本原则。

下面完成数据顺序存储,下图是准备好的一颗二叉排序树。

image-20211120121515801

假设现在要将 10存入上图的二叉树中,由于10>6,走右边,10>7,继续走右边,10>8继续走右边。所以10会插入到8的右孩子位置,如下图:

image-20211120121728508

假设现在继续将9插入树中,由于9>6,9>7,9>8,且9<10,所以9应该在6/7/8的右边且在10的左边,如下图:

image-20211120122028454

3.3 二叉树的问题

以上的操作看起来很顺利,但是其中却隐藏着问题。假设已有的二叉树是这样的:

image-20211120122255450

试着在二叉树中连续插入5,4,3,2

image-20211120123013367

发现二叉树变成这样一颗”歪脖子树“了。查询的节点时间复杂度退化成了O(N)。这个问题我们怎么解决呢?这个就要涉及到二叉树的平衡了。关于二叉树的平衡,下一章我们再详细的介绍。

四、总结

二叉树是数据结构的一种,本章介绍了满二叉树和完全二叉树。以及二叉查询树的查询操作和新增操作。使用二叉树来存储数据,既可以保证顺序,又可以提高查询效率。不过最后我们发现如果二叉树长歪了,查询效率就会变低,要解决这个问题,我们需要让二叉树自己平衡。关于二叉树的自平衡下章介绍。

欢迎关注公众号OpenCoder,来和我做朋友吧~❤😘😁🐱‍🐉👀