B 树
B树的定义
根据 Knuth 的定义,一个B树需要满足以下规则:
- 每一个节点,都最多拥有m个子节点。 (Every node has at most m children)
- 每一个非叶子的节点(不包括根节点),都最少拥有m/2个子节点。 (Every non-leaf node (except root) has at least ⌈m/2⌉ child nodes)
- 在根节点不是叶子节点时,最少拥有两个子节点。(The root has at least two children if it is not a leaf node)
- 一个拥有K个子节点的非叶子节点,拥有k - 1个关键字。(A non-leaf node with k children contains k − 1 keys)
- 所有叶子节点都出现在同一个层级,且不携带任何数据。(All leaves appear in the same level and carry no information)
B树的插入过程
m阶B树的插入过程如下:
- 初始化root节点,并向其中插入数据
-
当root节点数据超过m时,进行分裂,分裂过程如下:
- 获取root节点中数据的中间值k
- root节点中,所有数值小于k的数据,全部取出行成左叶子节点
- root节点中,所有数值大于k的数据,全部取出行成右叶子节点
- k值保留在root节点中
- 根据数据,向叶子节点插入数据
-
当某一个叶子节点中的数据超过m时,叶子节点进行分裂,分裂过程如下:
- 获取该叶子节点的中间值k
- 该叶子节点中,所有数值小于k的数据,全部取出行成新的叶子节点,并与该叶子节点的父节点相连
- 该叶子节点中,所有数值大于k的数据,全部取出行成新的叶子节点,并与该叶子节点的父节点相连
- k值上移到该叶子节点的父节点
-
重复步骤3-4,直到该叶子节点的父节点数据超过m,开始进行新一层节点的生成,具体步骤如下:
- 获取该叶子节点的父节点的中间值k
- 所有数据小于k的数据,全部取出行成左叶子节点与该叶子节点的父节点相连,然后,所有与该叶子节点的父节点相连的叶子节点中最大值小于k的节点与新的左叶子节点相连
- 所有数据大于k的数据,全部取出行成右叶子节点与该叶子节点的父节点相连,然后,所有与该叶子节点的父节点相连的叶子节点中最小值大于k的节点与新的右叶子节点相连
- 重复步骤3-5
设置m=3,然后插入[1...25]的过程如下:
B树的删除过程
m阶B树的删除过程如下:
- 查找key对应的位置
-
根据key对应的位置,在删除之后做不同的操作,具体情形如下:
-
如果key对应的节点是一个内部节点x(internal node),那么需要按照以下三种情况做判断:
- 如果x节点的子节点中,数据小于k的最邻近子节点y中存在大于t个数据,则在完成k的删除之后,将y节点中数值最大的数据挪到x节点中。
- 如果情形1中的y节点中存在的数据小于t,那么查找数据大于k的最邻近子节点z中的数据的数量是否大于t,如果大于t,则将z节点中的最小值挪到x节点中
- 如果情形2中的z节点数据的数量也小于t,那么直接合并y,z节点
- 如果x节点的子节点中,数据小于k的最邻近子节点y中存在大于t个数据,则在完成k的删除之后,将y节点中数值最大的数据挪到x节点中。
-
如果key节点对应的是一个叶子节点,那么在删除之后,需要根据以下情景做调整:
- 该结点key个数大于等于Math.ceil(m/2)-1,结束删除操作
- 如果兄弟结点数据个数大于Math.ceil(m/2)-1,则父结点中的key下移到该结点,兄弟结点中的一个key上移,删除操作结束
- 如果兄弟结点数据个数小于Math.ceil(m/2)-1,将父结点中的key下移与当前结点及它的兄弟结点中的key合并,形成一个新的结点。
-
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。