高度为5的3阶b树含有的关键字个数_树数据结构

本文介绍了二叉树、平衡二叉树、B树和B+树的相关知识。包括二叉树的插入、遍历和删除操作,平衡二叉树插入和删除时的平衡处理,B树的特性及插入、删除操作,以及B+树的特性和与B树的优劣对比,指出关系型数据库常用B+树存储数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、二叉树

二叉树可以使用一个链表数据结构来表示,其中每个结点就是一个对象。除了

和数据之外,每个结点包含属性
,它们分别指向结点的左孩子、右孩子和双亲。如果某个孩子结点和父结点不存在,则相应属性的值为
。根结点是书中唯一父指针为
结点。

是二叉树中的一个结点。如果
是左子树中的一个结点,那么
。如果
右子树中的一个结点,那么

1. 插入

假设有这样一组数

,按照顺序构造二叉树,步骤如下:

eb768bf320d859b2e3ac2cc0942184f2.png
插入 35,为根结点

de33c23815bbda1f0ac333a0403d6e3c.png
插入 27,由于比 35 小,所以为 35 左子树

464efac5fa17f845ac192d7e6319fb2f.png
插入 48,由于比 35 大,所以为 35 右子树

55bd1ff2aafcc39799b196f41be72dea.png
插入 12,由于比 35 小,所以在 35 的左边,比 27 小,所以为 27 左子树

3c3cf9973c218af7fa9466e9abcb7b42.png
插入 29,由于比 35 小,所以在 35 的左边,比 27 大,所以为 27 右子树

eda58e64070d2a759ef640caafb85d15.png
插入 38,由于比 35 大,所以在 35 的右边,比 48 小,所以为 48 左子树

14ba060330f53e1e004badd8bd031bcd.png
插入 55,由于比 35 大,所以在 35 的右边,比 48 大,所以为 48 右子树

是一个左右子树大小相对差不多的二叉树,同样的一组数,我们改变下排序,按照

顺序插入。

1adc92aadc8891273eab295db30040e5.png

由于升序插入,新插入的数据总是比已存在的结点数据都要大,所以每次都会往结点的右边插入,导致严重右斜。一颗树退化为一个线性链表,查找效率变的很低

2. 遍历

14ba060330f53e1e004badd8bd031bcd.png
  • 中序遍历:根的关键字
    位于其左子树的关键字值和右子树的关键字之间。中序遍历输出为:
  • 先序遍历:根的关键字在其左右子树的关键字值之前。前序遍历输出为:
  • 后序遍历:根的关键字在其左右子树的关键值之后。后续遍历输出为:

3. 删除

从一颗二叉搜索树中删除一个结点

,分为三种情况:
  • 如果
    没有孩子结点,那么只是简单地将它删除,并修改它的父结点,用
    做为孩子来替换
  • 如果
    只有一个孩子,那么将这个孩子提升到树中
    的位置上,并修改
    的父结点,用
    的孩子来替换
  • 如果
    有两个孩子,那么找
    的后继
    (一定在
    的右子树中,大于
    的最小关键字的结点,且
    结点一定没有左子树,否则
    不是最小关键字的结点),并让
    占据树中
    的位置,如果
    存在右子树
    ,让
    占据
    位置。
    原来左子树成为
    的新左子树,
    原来右子树成为
    的新右子树。

二、平衡二叉树

平衡二叉树是一种特殊的二叉树,满足二叉树的特性,同时还有一个特性:它的左右两个子树的高度差的绝对值不超过

,并且左右两个子树也是一颗平衡二叉树。

1. 插入

在所有的不平衡情况中,都按照先寻找最小不平衡树,然后寻找不平衡类别,只需要一次或两次旋转来恢复平衡,根据以下四种情况进行旋转。

  • LL:在 A 左子树的左子树插入结点而破坏平衡——右旋转。
  • RR:在 A 右子树的右子树插入结点而破坏平衡——左旋转。
  • LR:在 A 左子树的右子树插入结点而破坏平衡——先左旋后右旋。
  • RL:在 A 右子树的左子树插入结点而破坏平衡——先右旋后左旋。

1c4ac955fc42b2c500cf698a7b43c6ce.png
LL

dbd4dc82a0a0efbe2dbcabfbb5033a4a.png
RR

d0da677d5c1592dd90581b8c5a94bf69.png
LR 先对 B 结点左旋,再对 A 结点右旋

202fad8f4d8bb961cf312eebd3d5d428.png
RL 先对 C 结点右旋,再对 A 结点左旋

我们还是以下面这组数为例

11c5fed11598199fa3bb87e9a85183d4.png
插入结点 12

1e75ed2b53c2e144293cb9218d8da8b3.png
插入 27,由于比 12 大,所以为 12 右子树

d9e323b1f13e7a85c67dd08bdcca2c97.png
插入 29,由于比 12、27 大,所以为 27 右子树。12 结点,左右子树高度差大于 1,进行左旋

fa7f2e079e36edae642dbae4be1c3853.png
插入 35,由于比 27、29 大,所以为 29 右子树

a069a1a879a4777ae63e6e0dc526ec67.png
插入 38,由于比 27、29、35 大,所以为 35 右子树,结点 29 左右子树高度差大于 1,进行左旋

98c4a0cf8ce84fda1e696d8eb0ac5f3c.png
插入 48,由于比 27、35、38大,所以为 38 右子树,结点 27 左右子树高度差大于 1,进行左旋

4da5ff80163083cf8f1f1f9f6cffa3d9.png
插入 55,由于比 35、38、48 大,所以为 48 右子树,结点 38 左右子树高度大于 1,进行左旋

这颗树始终满足平衡二叉树的几个特性而保持平衡,避免了树退化为线性链表,查找效率和二分法查找一样。

2. 删除

和删除二叉树操作情况一致,分为上面三种情况,但是平衡二叉树删除结点后需要重新检查平衡性并修正。

1) 删除叶子结点

  • 将该结点直接从树中删除;
  • 通过向上遍历,计算其父结点是否失衡;
  • 如果父结点未失衡,则继续向上遍历父结点的父结点并计算是否失衡,反复直到根结点;
  • 如果父结点失衡,则判断是哪种失衡类型
    ,并对其进行相应的平衡化处理。处理后,如果发现以父结点为根结点的树的高度发生变化,继续遍历;如果高度未变化,说明祖先结点的高度不会有变化,可以直接退出。

5090a488fc89923f31b44784a0237a57.png
删除结点 F,导致结点 A 左右子树高度差大于 1(类似新增结点 G 导致),所以是 LL 型失衡

2)删除的结点只有左子树或者右子树

  • 将左子树或右子树替代原来删除结点的位置;
  • 从删除结点位置向上遍历判断是否失衡,具体做法和上面一样。

6ec008af8aed68c329dc66b4d50ec37b.png
删除结点 C,导致结点 A 左右子树高度差大于 1(类似新增结点 G 导致),所以是 LR 型失衡

3)删除的结点既有左子树又有右子树

  • 具体参考二叉树第三种删除情况;
  • 从后继结点的父结点开始向上遍历是否失衡,具体和前面一样。

563dff82fbee01f8f634d9ac0761bd97.png
删除结点 2,右子树找到后继结点 3,用结点 3 替代结点 2 的位置,用结点 3 的右节点 4 替代 结点 3 的位置;对结点 10 进行右旋;对结点 5 进行左旋

一颗平衡树能容纳的结点数和树的高度有关系,假设树的高度为

,第
层最多容纳的结点数量为
,整颗树最多容纳结点数为
万数据树的高度大概是
左右,也就是说从
万条数据中找一个数据,最坏情况下需要
次查找。

我们数据库中的数据基本都是存放在磁盘中,每次读取一个二叉树的结点就是一次磁盘 IO,这样我们找一条数据需要

次磁盘的 IO。

三、B 树

B 树是为磁盘或其他直接存取的辅助存储设备而设计的一种平衡搜索树,每个结点可以有很多孩子。一颗 B 树有如下特性:

  1. 每个结点
    有下面属性:1)
    当前存储在结点
    中的关键字个数;2)
    个关键字降序存放,使得
    3)
    一个布尔值,如果
    是叶结点,则为
    ;如果
    是内部结点,则为
  2. 每个内部结点
    还包含
    个指向其孩子的指针
    叶结点没孩子,所以它们的
    属性没有定义。
  3. 关键字
    对存储在各个子树中的关键字范围加以分割:如果
    为任意一个存储在以
    为根的子树中的关键字,那么:
  4. 每个叶子结点具有相同的深度,即树的高度
  5. 每个结点所包含的关键字个数有上界和下界。用一个称为
    树的
    最小度数固定整数
    来表示。1)除了根结点以外的每个结点必须至少有
    个关键字。因此除了根结点以外的每个内部结点至少有
    个孩子。2)每个结点至多可包含
    个关键字。因此内部结点至多可有
    个孩子。当一个结点恰好有
    个关键字时,称该结点时
    满的

1. 插入

由于不能将关键字插入一个满的叶子结点,故引入一个操作,将一个满的结点

(有
个关键字)按其
中间关键字
分裂为两个各含
个关键字的结点。中间关键字被提升到
的父结点,以标识两棵新树的划分点。但是如果
的父结点也是满的,就必须在插入新的关键字之前将其分裂,最终满结点的分裂都会沿着树向上传播。

假设这样一组数据

,构建
阶 B 树:

e04e7b13fbde8b178b68ade449d59ec2.png
插入 9

a198e7d986c0ff67fe369d5d387c9404.png
插入 2,2 比 9 小,所以排在左边

5f6bae0d931f0b32e567ebc8943305e8.png
插入 12,12 比 9 大,所以排在右边

ee7c6d96b07b9a4897d5d85d1a3f37c3.png
插入 1,结点的关键字超出 3,进行分裂,中间关键字 2 被提升到父结点

5a41f754e1ef78fabeff7bf2a38b34c9.png
插入 3

cab8be2d1b0239b59e9985b1558f5abf.png
插入 11,结点的关键字超出 3,进行分裂,中间关键字 9 被提升到父结点

06b060d38d6642c910d7b93a71483fc6.png
插入 13

ef7332295594913960566afde311f495.png
插入 15,结点的关键字超出 3,进行分裂,中间关键字 12 被提升到父结点

75896d7fc284bc4768f86a408cdd1ca9.png
插入 6

f8fa1d1595e828e8da5d472e77594b94.png
插入 8

e99df967ced118e679aea039ad130fa5.png
插入 5,结点的关键字超出 3,进行分裂,中间关键字 5 被提升到父结点;父结点的关键字超出3,进行分裂,中间关键字 5 被提升到父结点

790bbcde4c8bd5612e1ae640e95db4c0.png
插入 4

2. 删除

  1. 如果关键字
    在结点
    中,并且
    是叶结点,则从
    中删除
  2. 如果关键字
    在结点
    中,并且
    是内部结点,则做以下操作:1)如果结点
    中前于
    的子结点
    至少包含
    个关键字,则找出
    在以
    为根的子树中的前驱
    ,删除
    ,并在
    中用
    代替
    ;2)如果
    有少于
    个关键字,则检查结点
    中后于
    的子结点
    。如果
    至少有
    个关键字,则找出
    在以
    为根的子树中的后继
    ,删除
    ,并在
    中用
    代替
    ;3)否则,如果
    中都只含有
    的关键字,则将
    合并进
    中,删除结点
    中的
    和指向
    的指针。
  3. 如果关键字
    不在当前内部结点
    中,但是
    指向的子树中,如果
    只有
    个关键字,则做以下操作:1)
    的一个相邻的兄弟至少包含
    个关键字,则将
    中的某一个关键字降至
    中,将
    该相邻兄弟的一个关键字升至
    ,将该兄弟相应的孩子指针移动到
    中;2)如果
    和其所有相邻的兄弟都只包含
    个关键字,则将
    与一个兄弟合并,即将
    的一个关键字移动至新合并的结点,使之成为该结点的中间关键字。

d4644d496a8cb9ad0d082be98e85d1b7.png
删除 8:情况 1

f2370fbb76f24d3d9103d45a4f56fd27.png
删除 2:1)情况 3-1(从 x 遍历,x 不含关键字 2,它的子结点 y 含关键字,但 y 的关键字只有 t-1个,且相邻兄弟 z 包含 t 个关键字,将 x 中关键字 5 降至 y 中,将 z 中关键字 9 升至 x 中,同时将 z 的孩子指针 w 移到 y 中);2)情况2-2(继续遍历,y 含有待删除关键字 2,后继 3 替换 2的位置)

f12dfb4e6f997ae5b63715a9ee9c6ef8.png
删除 3:情况 2-3,结点 x 包含关键字 3,且 3 前后子结点 y 和 z 中的关键字数都为 t-1,z 和 y 进行合并

4ec56f25ee0eee9826e18c63df9e071b.png
删除 5:1)情况 3-2,从 x 开始遍历,y 和 z 都只有 t-1 个结点,所以合并 x, y, z 三个结点形成新结点 w;2)前于关键字 5 的结点 w 的关键字数为 t-1,用前驱 4 替代 5

四、B+树

B+树是由 B-树衍生来的,更适合实现外存储索引结构,具有特性:

  • 所有的非叶子结点只存关键字信息;
  • 所有卫星数据都存在叶子结点中;
  • 所有的叶子结点中包含了全部的数据信息;
  • 所有叶子结点之前用指针连接。

假设一组数据

,构建
的 B+树。

f72b35595b87a7d5216c44043bbfff62.png

B-树和B+树的优劣:

  • B-树非叶子结点也保存了具体数据,所以在查找某个关键字的时候找到即可返回。而B+树所有数据都在叶子结点,每次查找都要到叶子结点,所以在同样高度的B-树和B+树中,B-树查找某个关键字的效率更高点;
  • 由于B+树所有数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据时候,B+树只需要找到该关键字然后沿着链表遍历就可以了,而B-树还需要遍历该结点的根结点去搜索;
  • 由于B-树的每个结点都存储关键字+实际数据,而B+树非叶子结点只存储关键字信息,而每页的大小是有限的,所以同一页能存储B+树的数据更多;同样总量的数据,B-的深度会更大,增大查询时磁盘 I/O 次数,进而影响查询效率。

在关系型数据库中,都是选择 B+树的数据结构来存储数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值