数据结构树-->B树

目录

1. 数据结构树–>树基础
2. 数据结构树–>二叉树
3. 数据结构树–>二叉查找树\二叉排序树
4. 数据结构树–>平衡二叉树
5. 数据结构树–>霍夫曼树
6. 数据结构树–>红黑树
7. 数据结构树–>二叉堆
8. 数据结构树–>B树
9. 数据结构树–>B+树

B树

1. B树的定义

B 树是一颗多路不平衡树,我们描述一颗B树时需要指定它的阶数,eg: 这是一颗5阶B树,阶数表示了一个节点最多有多少孩子节点,一般用M表述。

m就是B树的阶数,当 m=2 时就是我们常见的二叉查找树。

一个m阶B树的定义如下:

  1. 每个节点最多有m-1个关键字。
  2. 根节点最少可以只有1个关键字
  3. 非根节点至少有m/2个关键字
  4. 所有叶子节点都位于同一层,或者说根节点到每个叶子节点的长度都相同。
  5. 每个节点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。

下面是一个3阶B树
数据结构树-->B树_第1张图片

  1. 根节点至少有一个数据。

  2. 非根节点至少有个 m/2 个数据。(无法除尽按照代码运算,eg: 5/2=2)

  3. 节点最多有 m -1 个数据。

  4. 所有叶子节点都处于同一层。

  5. 第五条也好理解,每个节点内的数据从小到大排列,每个节点左子树小于它的最小数据,右子树大于它的最大数据,中间子树数值在两个数据之间。

    eg: 3 5 数组在父节点 2 6 之间,3 5 节点属于中间子树。

2. B树的插入

B树的插入参考文章:B树和B+树的插入、删除图文详解

B树插入操作的逻辑:

  1. 根据要插入的Key的值,找到叶子节点插入数据。

  2. 判断当前节点是否满足节点最多 m-1 个数据,满足则结束,不满足则进行第3步。

  3. 以节点中间的 key 值为中心,分裂为两个节点,中间的key值插入到父节点中,这个key的左子树指向分裂后的左半部分,右子树指向分裂后右半部分。

    然后以key值所在节点进行第 2 步的判断。

看参考文章上的举例,以5阶B树为例。

2.1 B树中插入 39 、22、97、41

在这里插入图片描述

  1. 找到要插入的节点(根节点), 插入元素。
  2. 节点元素从小到大排列。
  3. 节点元素个数满足 m-1 , 结束插入。

2.2 B树中再插入 53

在这里插入图片描述

数据插入后节点数据个数为5,超多了节点最多m-1,所以这个节点要分裂。进行插入操作的第3步。

  1. 以节点数据 41 为中间key, 分裂为两部分, 22、39 与 53、97。
  2. 节点数据41 插入到父节点,父节点没有数据,则41单独构成一个根节点。
  3. 新的根节点左子树指向 22、39构成的节点,右子树指向 53、97构成的节点,
  4. 判断父节点, 父节点数据个数小于 m-1, 则插入结束。

最后形成的B树为:

数据结构树-->B树_第2张图片

2.3 B树依次再插入13,21,40

根据插入值的大小,我们知道这3个值都会插入到上图左叶子节点中,则左叶子节点形成了, 13、21、22、39、40,的数据。

进入步骤2,判断节点超出 m-1 个数据,则左叶子节点开始分裂。

  1. 以22数据中中心,分裂为两个13、21与 39、40。 22数据插入到父节点。
  2. 新的节点 13、21作为22的左子树, 39、40作为22的右子树。
  3. 判断父节点,插入结束。

最后形成的B树为:
在这里插入图片描述

如上图,形成了B树的节点用有了中间子树。

2.4 节点浪费情况

看下图
数据结构树-->B树_第3张图片

我们知道当一个B树确定了它的阶数,则这棵B树节点的大小是固定的(m-1),,但在我们实际的操作中,总会有节点无法再插入,这种情况就造成了固定节点大小的节点浪费情况。

例如:节点 28、29, 由于父节点的情况我们知道,它无法再插入数据,节点后面的空间就造成了浪费。所以如果记录先按key的大小排好序,再插入到B树中,

结点的使用率就会很低,最差情况下使用率仅为50%。

3. B树的删除

B树的插入我们了解到了中间节点的上移,在B树的删除中我们将插入操作反向进行,让类似的中间节点下移,其他节点合并成一个节点。

步骤:

  1. 首先要删除数据的节点为非叶子节点,用该节点数据的后继节点数据来代替要删除数据,这个方式与二叉查找树的删除类似,找到后继节点数据(右子树最小值或左子树的最大值),然后对后继节点进行第二步判断,如果要删除的数据在叶子节点,则删除后直接进入第二步。
  2. 判断节点是否符合B树特性,特性:非根节点至少有个 m/2 个数据。满足则删除结束,否则进入第3步。
    1. 如果兄弟节点数据个数大于 m/2,则父节点数据下移到该节点,兄弟节点中一个数据(最大值或最小值)上移到原父节点位置,删除结束。
    2. 如果不是1的情况,则父节点数据下移到该节点,该节点与兄弟节点合拼,形成新的节点,新节点父节点指向原父节点中的数据。父节点数据进入步骤2进行递归操作。

我们以2.4 节点浪费情况的图为基础来研究删除的步骤。

3.1 删除21

节点数据删除后,节点任旧符合B树特性,删除结束。

3.2 删除 27

数据结构树-->B树_第4张图片

  1. 查找节点数据27的后继数据,与二叉查找树删除类似,找到数据右子树最小值,为节点数据28, 节点数据28替换要删除的节点数据27.
  2. 查看兄弟节点数据个数大于 (m/2)—>2,则父节点下移到该节点,兄弟节点是左子树,则兄弟节点最大值上移,完成删除。

删除结果:
数据结构树-->B树_第5张图片

3.3 删除32

  1. 32所在节点为叶子节点,直接删除,则该节点进入第二步判断。

  2. 该节点数据个数小于2,不满足B树特性,进入第三步判断,兄弟节点数据个数为2,满足第三步 第2条。

  3. 父节点下移,该节点与兄弟节点合并,形成新的节点,将新节点的父节点指向原父节点数据的前一个数据。父节点变为当前节点进行判断。

  4. 父节点满足B树特性,删除结束。
    数据结构树-->B树_第6张图片

3.4 删除40

删除40的操作和删除32的操作是一样的,这里不一样的一点是我们可以选择左兄弟节点也可以选择右兄弟节点,都可以达到删除的目的。

删除结果:
数据结构树-->B树_第7张图片

你可能感兴趣的:(数据结构,数据结构)