对B-树的理解

目录

前言-为什么要使用B-树?

首先,我们正常的搜索都有一下方式:

  1. 搜索二叉树,极端场景下会退化,类似于单支,此时的效率变成了O(N);
  2. 为了解决1的问题,提出了平衡树的概念,左右子树的高度差不大于1,AVL树,红黑树。该效率为O(logN),其中map/set就是由此构建的;
  3. 更好的搜索结构则有哈希/散列表,该效率为O(1),--unordered_map/unordered_set
  4. 跳表、字典树

上面的结构都是完成内存中数据的搜索查找问题

但假设此时的数据量很多 ,在内存中存放不下,数据要存到磁盘中,上面的数据结构就不好了,虽然可以把内存在磁盘的地址使用AVL树来存储,查找的时间复杂度为O(logN),但是该复杂度在内存中访问非常快,在磁盘中,logN次磁盘IO访问会非常慢。 如果换成哈希表,变成O(1),在极端情况下,哈希表冲突十分厉害,一个桶中数据太多,会影响效率,并且哈希表中存在很多附带数据(表结构、节点中的指针等),数据量很大时,内存占用很多。B树则能解决这些问题。

B-树概念

B树是一种平衡的多叉树,一颗M阶(M>2)的B树,为平衡的M路平衡搜索树,可以是空树或者满足以下性质:

  1. 根节点至少有两个孩子
  2. 每个非根节点至少有M/2(向上取整)个孩子,至多有M个孩子
  3. 每个非根节点至少有M/2-1(向上取整)个关键字,至多有M-1个关键字,并且以升序排列
  4. key(1)和key(i+1)之间的孩子节点的值介于key[i]、key[i+1]之间
  5. 所有的叶子节点都在同一层

对上述性质进行总结来说:

根节点:关键字数量[1,M-1],孩子数量[2,M]

非根节点:关键字数量[M/2-1, M-1],孩子数量[M/2,M]

每个节点中,孩子的数量比关键字的数量永远要多一个

那么为什么会有这样的性质呢?结合例子来进行理解
针对根节点的数量范围分析

首先,一个关键字会有两个孩子(左孩子和右孩子),其中和相邻的关键字会共有一个孩子,即关键字1的右孩子也是关键字2的左孩子,那么孩子的数量就会比关键字的数量多一个。

针对非根节点的数量范围分析

假设M等于3,那么根节点的关键字数量最多只能放2个,如果放到了3个,则违反了规则,根节点最多存M-1个关键字,那么就会进行分裂,创建一个兄弟节点,右边M/2的值拷贝到兄弟节点中,中间值插入到父亲,如果没有父亲,则创建新的父亲,该值作为新的根。也就是上图右下角的节点,关键字70超出范围,则进行分裂,将70分裂为兄弟节点,50插入到父亲节点。

那么为什么分裂的时候要提中位数插入到父亲呢?

因为分裂新增一个兄弟节点,对于父亲而言,多了一个孩子,还得多一个关键字,这样才能保持孩子的数量比关键字数量多一个。

结合分裂的思想:

如果M是奇数,分裂时两边数量为M/2,中间值插入到父亲。(比如M=9,左右各为4,剩余的一个节点插入到父亲,如果没有父亲则创建)

如果M是偶数,因为两边要有一个需要插入到父亲,因此总有一边要少一个,一边是M/2,一边是M/2-1。(比如M=10,左右为5和4或者4和5,剩余一个插入到父亲,如果没有父亲则创建)

相关推荐
Beauty.56836 分钟前
P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布
数据结构·c++·算法
爱棋笑谦38 分钟前
二叉树计算
java·开发语言·数据结构·算法·华为od·面试
jimmy.hua1 小时前
C++刷怪笼(5)内存管理
开发语言·数据结构·c++
Freak嵌入式1 小时前
全网最适合入门的面向对象编程教程:50 Python函数方法与接口-接口和抽象基类
java·开发语言·数据结构·python·接口·抽象基类
MogulNemenis2 小时前
力扣春招100题——队列
数据结构·算法·leetcode
学java的小菜鸟啊2 小时前
第五章 网络编程 TCP/UDP/Socket
java·开发语言·网络·数据结构·网络协议·tcp/ip·udp
菜鸟求带飞_3 小时前
算法打卡:第十一章 图论part01
java·数据结构·算法
是小Y啦3 小时前
leetcode 106.从中序与后续遍历序列构造二叉树
数据结构·算法·leetcode
万河归海4283 小时前
C语言——二分法搜索数组中特定元素并返回下标
c语言·开发语言·数据结构·经验分享·笔记·算法·visualstudio
秋夫人5 小时前
B+树(B+TREE)索引
数据结构·算法