从B-树到B+树,再到红黑树

BTree

BTree的特点

1.B-树的查找,删除,顺序读取,插入时间复杂度为O(logn)

2.若为M阶的B树 -根节点至少有两个节点,并且至少可以只有一个key

3.每个节点最多有M-1个key,最多有M个子节点,并且以升序排列,至少M/2 - 1个key,至少要有M/2个子节点

4.每个叶子节点都在同一层

其实总结来说,最关键的就是作为一个M阶B树,这个M是用来规定每个节点的子节点不能超过M个,并且当前节点至少要有M/2个节点,而每个节点中的Key值对于其子节点来说,其实是一个范围。所以n个key,就有n+1个范围,也就是说可以有n+1个子节点,所以相对应的,每个节点不能超过M-1个key,但不能少于M/2-1个key。

从B-树到B+树,再到红黑树

所以根据这些特点,我们插入删除查询的时候就只要遵循这些规则就好了(图为5阶BTree)

BTree插入

插入的时候,肯定是从root开始插入,那么能遇到的情况,我们自己可以根据BTree的规则归纳一下

第一个,如果我们插入2,在图中很容易看到只要插入1和3中间就好了,插入节点的数量不超过规定的M-1个,那么直接插入就好了

第二种情况,如果我插入的时候当前节点超过了M个怎么办?比如插入22的时候,在22,23,24,25,26包含5的key,那么这个节点就不符合规定了,那么我们要做的就是怎么把这个节点给分裂开,这个时候我们以中间节点24为界限,将24提到父节点组成17,20,24,22,23和25,26分别组成25的左右子节点

从B-树到B+树,再到红黑树

第三种情况,其实就是第二种情况衍生的,如果我根节点也是四个key值了怎么办,比如我们现在有下面的情况,(当然子节点不止两个,其他的没画出来),这个时候我们如果插入29的话,叶子结点超过4,这个时候应该提27到父节点,组成16,17,20,24,27,但是这样一来父节点就不满足条件了,所以这样时候继续向上提20,得到第二张图

从B-树到B+树,再到红黑树

从B-树到B+树,再到红黑树

所以总结就知道BTree的插入,要么正常插入,要么超过M-1个key值,取中间的值往上提,然后分裂当前节点就可以了。

BTree删除

插入的时候会遇到的问题是插入节点超过M-1个,删除的时候相对应的就是删除完了当前节点key数目小于M/2-1个了。

第一种去情况,我们删除了一个非叶子节点,那么他的左右两侧接的子节点肯定得有人继承,那么一般取第一个比删除节点大的节点继承这两个子节点,比如删除24,那么就是25往上提,来继承22,23和26这两个子节点

从B-树到B+树,再到红黑树

第二种情况,如果删除的节点数目在删除这个节点之后小于了M/2-1当M=4的时候节点数目不能小于1,就比如在上图中我们继续删除26,这个时候25,27中间的字节点就为空了(如果M>4的话不一定为空,可能为1或者2,但是违背了每个节点数目必须大于等于M/2-1的规则),这个时候如果某个兄弟节点的数目大于M/2-1,那么直接将与该兄弟节点包夹的可以值向下移,兄弟节点提一个上来,比如这里我们题23上去,得到

从B-树到B+树,再到红黑树

第三种情况,我兄弟节点可以支援的时候是第二种情况,那么如果我兄弟节点自身难保了咋办,这就是第三种情况,比如这个时候我删掉22,同时25节点只有一个key不可能去支援22,那么这个时候我们就只能跟兄弟合并了,这里就是把23下移,与25合并,当然在第二种情况和第三种情况如果父节点移下来的时候,其实也相当于删除了这个节点,检查的过程从第一种情况-第三种情况去套用就好了,处理方法时一样的,比如这里如果再删除27,因为兄弟节点可以支援,那么就20下移到27的位置,17提到20的位置,因为17有右节点,这个时候应该将20与右节点合并,按照是否超过M来处理。

从B-树到B+树,再到红黑树

BTree性能

通过上面的插入和删除,其实查询也是一样的,要增删改查BTree的性能其实都是logn,需要比较的次数并不比二叉树少,所以在这方面BTree和二叉树有相同的性能,但是BTree的优势在于比二叉树的深度浅,这样的话可以减少IO的次数,在需要将数据读到内存进行操作时,可以大幅度提高性能。

 

B+树

在B-树的基础上,提出了B+树,更进一步提升了B-树的性能,

改变第一个,是在非叶子结点上不存数据,只存索引,这样进一步减少IO的次数,提升性能,

第二个是,所有数据在叶子结点上,并且用链表串联起来,所以在范围查询的时候,非常方便,只要查到一头一尾的位置,然后通过链表查询就行了。

因为非叶子节点只存索引,所以B+树在相同的磁盘页中,每个节点可以存比B树更多的信息,所以可以使得B+树更浅,并且更胖。

从这个特点来看,B+树其实不管任何查询,复杂度必是logn,不会比logn更大,也不会比logn更小,而B-树不稳定,可能快,也可能慢,但是在范围查询上,肯定是比不过B+树的。

B+树的结构特性和插入删除操作跟B树基本一直,M阶B+树每个节点最多为M-1个key,做多拥有M个子节点(当然有些资料也显示的是M-1个子节点,这里用M个),插入删除的情况也基本一直。

BTree和B+树的优劣

从图看看B树和B+树的区别

从B-树到B+树,再到红黑树

从B-树到B+树,再到红黑树

第一个,因为B树中的非叶子结点不仅要存索引信息,而且包含了数据信息,而在B+树中我们可以看到,他只存了索引信息,所以B+树中,在相同的页大小中,B+树的每一层的节点key存放更多的信息,这也就导致了B+树可以很宽,这样又可以使得B+树很矮,这样一来基本IO次数就控制在2次左右,大大的减少了IO次数。

第二个因为B+树在叶子结点用一条双向链表将所有叶子结点连接,所以在范围查询的时候非常方便,这一点是B树做不到的。

所以总结来说:B+树的效率更加稳定(IO次数为两次,复杂度稳定在logn),并且更适合范围查询,IO代价更低。

 

红黑树

红黑树的特性

红黑树从本质上来说其实算是平衡二叉树,只是为了实现严格的平衡,每次旋转会花费很大的功夫,这样一来性能就会很差,所有红黑树在这基础上改进了平衡二叉树,他成了一个放松版的平衡二叉树,而红黑接节点其实就是用来规范这个平衡二叉树的特性的一个方法。

1.每个节点或者是黑色,或者是红色。

2.根节点是黑色。

3.每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]

4.如果一个节点是红色的,则它的子节点必须是黑色的。

5.从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

特性3中的叶子节点,是只为空(NIL或null)的节点。

特性5,确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接*衡的二叉树。

所以理解红黑树其实主要就是平衡二叉树加红黑节点,而相对应的平衡二叉树的左旋右旋也是红黑树保持特性的关键。(这里左旋和右旋先放着,有机会再来补充)

 

上一篇:C++基础语法梳理:数据库丨BTree索引


下一篇:Mysql BTree和B+Tree详解BTree和B+Tree详解