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)

image

B树的插入过程

m阶B树的插入过程如下:

  1. 初始化root节点,并向其中插入数据
  2. 当root节点数据超过m时,进行分裂,分裂过程如下:

    1. 获取root节点中数据的中间值k
    2. root节点中,所有数值小于k的数据,全部取出行成左叶子节点
    3. root节点中,所有数值大于k的数据,全部取出行成右叶子节点
    4. k值保留在root节点中
  3. 根据数据,向叶子节点插入数据
  4. 当某一个叶子节点中的数据超过m时,叶子节点进行分裂,分裂过程如下:

    1. 获取该叶子节点的中间值k
    2. 该叶子节点中,所有数值小于k的数据,全部取出行成新的叶子节点,并与该叶子节点的父节点相连
    3. 该叶子节点中,所有数值大于k的数据,全部取出行成新的叶子节点,并与该叶子节点的父节点相连
    4. k值上移到该叶子节点的父节点
  5. 重复步骤3-4,直到该叶子节点的父节点数据超过m,开始进行新一层节点的生成,具体步骤如下:

    1. 获取该叶子节点的父节点的中间值k
    2. 所有数据小于k的数据,全部取出行成左叶子节点与该叶子节点的父节点相连,然后,所有与该叶子节点的父节点相连的叶子节点中最大值小于k的节点与新的左叶子节点相连
    3. 所有数据大于k的数据,全部取出行成右叶子节点与该叶子节点的父节点相连,然后,所有与该叶子节点的父节点相连的叶子节点中最小值大于k的节点与新的右叶子节点相连
  6. 重复步骤3-5

设置m=3,然后插入[1...25]的过程如下:

image

B树的删除过程

m阶B树的删除过程如下:

  1. 查找key对应的位置
  2. 根据key对应的位置,在删除之后做不同的操作,具体情形如下:

    1. 如果key对应的节点是一个内部节点x(internal node),那么需要按照以下三种情况做判断:

      1. 如果x节点的子节点中,数据小于k的最邻近子节点y中存在大于t个数据,则在完成k的删除之后,将y节点中数值最大的数据挪到x节点中。

        image

      2. 如果情形1中的y节点中存在的数据小于t,那么查找数据大于k的最邻近子节点z中的数据的数量是否大于t,如果大于t,则将z节点中的最小值挪到x节点中
      3. 如果情形2中的z节点数据的数量也小于t,那么直接合并y,z节点

        image

    2. 如果key节点对应的是一个叶子节点,那么在删除之后,需要根据以下情景做调整:

      1. 该结点key个数大于等于Math.ceil(m/2)-1,结束删除操作
      2. 如果兄弟结点数据个数大于Math.ceil(m/2)-1,则父结点中的key下移到该结点,兄弟结点中的一个key上移,删除操作结束

        image

      3. 如果兄弟结点数据个数小于Math.ceil(m/2)-1,将父结点中的key下移与当前结点及它的兄弟结点中的key合并,形成一个新的结点。

        image


KuHa
21 声望6 粉丝

会写很多种hello world