1、二叉树存在 形成 过长的单链表的问题。后面引入平衡二叉树
图:
文:
我们本章的重点这样讲解一下,
只是为了让大家对索引的数据结构呢有一个深刻的印象。
因此我们将通过图的演示去讲解,
代码的话呢,大家可以课下去了解一下,
慕课网也有专门讲解数据结构的经典课程,
面试也会用到的哦。
众所周知,
2叉查找树是每个节点最多有两个子树的数结构。
通常子树被称作左子树或者右子树。
2叉查找树的重要性质是对于树中的每一个节点X,
这里哈,
就是以这个根节点5来做比方,
它的左子树的任意节点的值呢?
均小于X2小于5同时呢,
柚子树上的任意节点的值呢,
均大于X,
也就是大于我们5。
那如果用2叉查找树来作为我们的索引,
确实能够提升查询效率。
这里需要大家注意的是,
我们说的索引的存储块,
和我们之前说的数据库的最小存储单位块或者页,
实际上并非一一对应,
只是为了方便我们的理解呢。
先将其一一对应起来了,
每个存储块存储的是关键字,
还有指向子树的指针。
像这棵树,
它不仅仅是2叉树,
还是平衡二叉树。
那什么是平衡2叉树呢?
就是它的任意一个节点的左子树,
它的高度呢,均不超过1。
那这里我们从根部开始,
根部的左子树呢,
比根部6子树呢,
它的高度呢要差1,
右子树比较高一些。
那到这个底部呢,
左右子树的高度呢是一样的,
总之呢它的高度呢是不能超过1的。
那2叉查找树的查找用的是2分查找,
比如说我们要搜6,
那这里呢,
6要比5要大,
因此我们就要从右孩子去查找那个孩子。
当我们就来到了7,
7呢,
它会比6大,
因此呢我们就会去查7的左孩子。
这样子呢我们就能定位到6了。
一位是对半搜索,
所以它的时间复杂度呢是大O的log(N)
因此其查询效率呢是非常高的。
但是呢,
它也有缺点。
首先咱们的数据库的数据呢,
可能面临着增加和删除。
那我们假定一下啊,
在这里呢,
我们经过数据的删除了之后呢,
节点2还有节点6都被删除了。
同时呢,
我们新增了这个关键值为11的节点。
那根据2叉查找树的特性呢,
它会被插入到这个9的关键字的右边右子树当中。
这里啊,
插入了一个11,
那紧接着我们又插入了13。
那又根据这个平衡2叉树的这个插入原则呢,
我们就会插入到这个11的右子树当中13,
那它最终呢就会也变成这样子,
就变成了一个线性的2叉树了。
那么它的这个查询时间复杂度呢,
就变成了大O的N,
大大降低了查询效率。
有的同学会说,
我们就可以利用树的一个旋转的特性,
来保持这棵树是平衡2叉树,
这样其时间复杂度呢会维持在大O的log(N)就OK了。
这样确实解决了第一个问题,
但是它还会有第二个问题。
咱们之前说了,
影响程序运行速度的瓶颈在哪里?
对了,
就是IO。
如果我们假定这些索引会都在磁盘中,
那刚刚呢?
检索来讲,
去找6会先发生一次IO,
将这个跟着数据呢读入到我们的内存当中,
那之后呢,
再发生比赛,
又将其读入进来。
紧接着呢,
又发生了一次IO,
五六级检索深度呢,
每增加1就会发生lyft平衡。
2叉树也好,
红黑思路也罢,
每个节点最多只能有两个孩子,
而咱们的数据块会非常的多,
因此为了组织起这些数据块,
咱们的树的深度呢就会很深很深,
IO的次数呢也会很多。
这样数据1多,
其检索性能比咱们之前说的全表扫描要慢很多,
根本就没法满足我们的优化查询的需求了。
那咱们还有什么办法能够既降低查询的时间复杂度,又降低IO的次数呢,
主要就是让树变得矮一些呢,
每个节点能存储的数据呢多一些,
这个时候咱们就想到B树了。