B树

B树(B-树或B_树)

  最近需要了解B树的相关知识,故在此刨根问底从二叉查找树看起。并做以下记录。以下转自寒江独钓的博客。

1、二叉查找树

  二叉查找树(Binary Search Tree)的定义如下:

  1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值。
  2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值。
  3. 任意节点的左右子树也分别为二叉查找树。
  4. 没有键值相等的节点。

2、2-3树

  和二叉树不一样,2-3树运行的每个节点保存 1 个或者 2 个的值。对于普通的 2 节点,它保存一个 key 和左右两个子节点。对于 3 节点,它保存两个 key。2-3树的定义如下:

  1. 要么为空,要么满足以下条件。
  2. 对于 2 节点,该节点保存一个 key 及其对应的 value,以及两个指向左右节点的地址。左节点也是个2-3节点,所有的值都比 key 小,右节点也是一个2-3节点,所有的值都要比key大。
  3. 对于 3 节点,该节点保存两个 key 和其对应的 value,以及三个指向左中右节点的地址。左节点也是一个2-3节点,其中所有的值均要比当前节点的两个 key 值中最小的那个还要小。中间节点也是一个2-3节点,中间节点的 key 值要在当前节点中的两个 key 之间。右节点也是一个2-3节点,节点的 key 值要比当前节点的两个 key 中最大的那个还大。

3、红黑树

  红黑树的主要是想对2-3数进行编码,尤其是对2-3树中的 3-nodes 节点添加额外的信息。红黑树中将节点之间的链接分为两种不同类型,红色链接,他用来链接两个2-nodes节点来表示一个3-nodes节点。黑色链接用来链接普通的 2-3 节点。特别的,使用红色链接的两个 2-nodes 来表示一个 3-nodes 节点,并且向左倾斜,即一个 2-node 是另一个 2-node 的左子节点。这种做法的好处是查找的时候不用做任何修改,和普通的二叉查找树相同。

  红黑树是一种具有红色和黑色链接的平衡查找树,根据以上描述,红黑树定义如下:

  1. 红色节点向左倾斜。
  2. 一个节点不可能有两个红色链接。
  3. 整个树完全黑色平衡,即从根节点到所以叶子结点的路径上,黑色链接的个数都相同。

4、B树

  1970年,R.Bayer 和 E.mccreight 提出了一种适用于外查找的树,它是一种平衡的多叉树,称为B树(或B-树、B_树)。一棵 M 阶 B 树(balanced tree of order m)是一棵平衡的 M 路搜索树。同时 B 树也可以看做是对 2-3 树的一种扩展,它允许每个节点至多有 M-1 个子节点。一个 M 阶的 B 树定义如下(出自数据结构C语言版-严蔚敏):

  • 树中的每个节点至多有 m 棵子树(即每个非节点至多有 m - 1 个 key)。
  • 若根节点不是叶子节点,则至少有两棵子树。
  • 除根节点之外的所有非终端节点至少有 m/2 棵子树(即每个非根节点所包含的关键字个数 j 满足: m/21jm1
  • 所有的非终端节点包含下列信息数据( n,A0,K1,A1,...,Kn,An )。 其中 Ki 为关键字且 KiKi+1 Ai(i=0,...,n) 为指向子树根节点的指针。
  • 所有的叶子节点都出现在同一层次上。
### B的数据结构和实现 B是一种自平衡的搜索树,广泛应用于数据库和文件系统中。其设计目的是为了减少磁盘访问次数,提高数据检索效率。B的每个节点可以包含多个关键字和子节点指针,且所有叶子节点位于同一层。 #### 1. B的基本定义 B由节点组成,每个节点包含一组关键字和一组子节点指针。对于一个最小度数为 \(t\) 的B,有以下特性[^2]: - 每个节点最多包含 \(2t-1\) 个关键字- 根节点至少包含一个关键字- 非根节点至少包含 \(t-1\) 个关键字- 如果某个节点是非叶子节点,则它包含 \(n\) 个关键字和 \(n+1\) 个子节点指针,其中 \(t \leq n \leq 2t-1\)。 - 所有叶子节点都在同一层。 #### 2. B节点的结构 在代码实现中,B的节点通常定义如下[^2]: ```c typedef int KEY_VALUE; typedef struct _btree_node { KEY_VALUE *keys; // 关键字数组 struct _btree_node **childrens; // 子节点指针数组 int num; // 当前节点的关键字数量 int leaf; // 是否为叶子节点 } btree_node; ``` #### 3. B的操作 B的主要操作包括插入、删除和查找。以下是这些操作的基本描述: ##### (1) 插入操作 当向B中插入一个新关键字时,可能需要分裂节点以保持的平衡。具体步骤如下: - 如果根节点满,则创建一个新的根节点,并将原根节点作为其子节点。 - 自顶向下查找合适的位置插入关键字- 如果某节点已满,则将其分裂为两个节点,并将中间关键字上移至父节点。 ##### (2) 删除操作 删除关键字时,可能需要合并或重新分配节点中的关键字以保持的平衡。具体步骤如下: - 查找待删除的关键字- 如果关键字存在于非叶子节点,则用其前驱或后继替换该关键字- 如果删除导致某节点的关键字数量低于下限,则从兄弟节点借关键字,或与兄弟节点合并。 ##### (3) 查找操作 查找操作通过比较关键字和节点中的值,逐步缩小搜索范围。具体步骤如下: - 从根节点开始,逐层向下查找。 - 在当前节点中查找目标关键字,如果找到则返回;否则进入相应的子节点继续查找。 #### 4. 示例代码 以下是一个简单的B插入操作的伪代码示例: ```c void btree_insert_nonfull(btree_node *node, KEY_VALUE key) { int i = node->num - 1; if (node->leaf) { // 如果是叶子节点 while (i >= 0 && node->keys[i] > key) { node->keys[i + 1] = node->keys[i]; i--; } node->keys[i + 1] = key; node->num++; } else { // 如果是非叶子节点 while (i >= 0 && node->keys[i] > key) { i--; } i++; if (node->childrens[i]->num == 2 * t - 1) { // 如果子节点已满 split_child(node, i); if (key > node->keys[i]) { i++; } } btree_insert_nonfull(node->childrens[i], key); } } ``` #### 5. B与B+的对比 尽管B功能强大,但在实际应用中,B+更为常用。B+对B进行了优化,主要改进点包括[^1]: - 所有关键字都存储在叶子节点中,便于范围查询。 - 叶子节点之间通过链表连接,支持顺序访问。 - 非叶子节点仅用于索引,存储实际数据。 ### 总结 B是一种高效的多路平衡搜索树,适用于大规模数据存储和检索场景。其核心在于通过节点分裂和合并保持的平衡性,从而确保操作的时间复杂度为 \(O(\log n)\)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值