B树

HDF文件格式采取了B树对数据进行存储,下面的文章主要来源于网络。
对 于一维升序或降序数据序列(假设其个数为N)来说,可以采用两分检索的方法来迅速地找到需要插入或删除元素的位置。但是当采用顺序存储的方式时,为插入一 个元素,需要将其以下的数据均进行后移;为删除一个元素,需要将以下的数据进行前移。为避免大量的数据移动,提高插入和删除的工作效率,研究者提出了多种 解决方法,B树就是其中较好的一种方案。
B 树是由一系列节点(SQL Server数据库采结构进行数据存储)所构成,它的每一个节点均由2m个数据域和2m+1个指针域所构成,每个节点的数据从左向右成升序排列。一般情况 下,B树的每个节点中的数据域不一定存放满数据,但基本上每个节点存放的数据数大于用B树m个。如下图所示:
  
  
B 树中父节点与子节点中的数据之间具有如下关系:父节点中每一数据域中存放的数据,均大于该数据域左侧指针指向的子节点中的所有数据,也小于该数据域右侧指 针指向子节点中的所有数据。以图2-2所示的B树来看,节点A中的数据0.25,其左侧的指针指向节点B,B中的数据均小于0.25,其右侧的指针指向 C,C中的数据也均大于0.25。
为建立一棵B树,需要将一个一个的数据插入其中。
当 需要在上面所示的B树中插入一个数据,例如是0.65,首先需要查询其应插入的位置。首先将根节点的数据与带插入数据向比较,其结果发现应插入在0.40 与0.72之间。而后,根据这两个数据之间的指针所值的位置,查到所指向的子节点D。比较之后确认应插入在数据0.60之后,当检查0.60右侧的指针后 发现该指针为空,由此确认应插入在节点D中数据0.60之右侧,恰巧在这个位置是空的,因此插入数据0.65后即完成了所需的插入工作。这是存在的另一种 可能性,是在0.60右侧有另外的数据,但节点D中还有空间允许填入新的数据,这是需要将0.60后面的数据进行右移,空出位置来插入0.65这一数据。
当 查询到插入位置,却发现该节点已填满数据时,我们需要进行节点的分割。仍以上述B树为例,设需要插入的数据是0.10。采用相同的方法,确认需要插入的位 置在节点B的数据0.12的左侧,但由于节点B已填入了四个数据,必须建立新的节点存放数据。为此,我们将原节点中存放的数 据和待插入的数据一起,找寻其中间数据,根据中间数据将这2m+1个数据分为两部分:小于中间数据的m个数据存入新的节点B1,大于中间数据的m个数据存 入节点B2中,将中间数据存入节点B的父节点A中,同时对中间数据两侧的指针加以处理,使其指向节点B1和B2。当出现父节点同样数据存满的情况时,采用 类似的方法将父节点进行相应的分割。 
 
06-14
### 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、付费专栏及课程。

余额充值