B树:原理、操作及应用

B树:原理、操作及应用

  • 一、引言
  • 二、B树概述
    • 1. 定义与性质
    • 2. B树与磁盘I/O
  • 三、B树的基本操作
    • 1. 搜索(B-TREE-SEARCH)
    • 2. 插入(B-TREE-INSERT)
    • 3. 删除(B-TREE-DELETE)
  • 四、B树的C代码实现示例
  • 五、总结

一、引言

在现代计算机科学中,高效的数据存储和检索是许多应用程序成功的关键。B树(B-tree)是一种自平衡的树,它能够保持数据稳定有序,其插入与查询的时间复杂度都是对数级别的,非常适合于磁盘等辅助存储器的存取系统。本文将详细介绍B树的基本原理、基本操作,并通过伪代码和C代码示例来解释其实现。

在这里插入图片描述

二、B树概述

1. 定义与性质

B树是一种多叉树,每个节点可以包含多个关键字和多个子节点。一个m阶的B树(m≥2)满足以下性质:

  • 每个节点至多有m个孩子。
  • 除了根节点外,每个非叶子节点至少有⌈m/2⌉个孩子。
  • 根节点至少有两个孩子,除非它是叶子节点。
  • 所有叶子节点都在同一层,并且不带信息(可以视为外部节点或查找失败的节点)。
  • 非叶子节点包含n个关键字信息(K₁, K₂, …, Kₙ),且满足K₁ < K₂ < … < Kₙ。
  • 非叶子节点的第i个子树中的所有关键字都在K_{i-1}和K_i之间(其中,K₀表示一个比该节点所有关键字都小的值,K_{n+1}表示一个比该节点所有关键字都大的值)。

2. B树与磁盘I/O

由于磁盘I/O操作通常比内存操作慢得多,因此,在设计和实现数据结构时,尽量减少磁盘I/O次数是关键。B树的设计充分考虑了磁盘的存取特性,通过增加树的扇出(即每个节点的子节点数)来降低树的高度,从而减少了查找过程中所需的磁盘I/O次数。

三、B树的基本操作

1. 搜索(B-TREE-SEARCH)

B树的搜索操作与二叉搜索树类似,从根节点开始,根据关键字的大小决定向下搜索的路径,直到找到目标关键字或到达叶子节点为止。以下是B树搜索的伪代码示例:

B-TREE-SEARCH(x, k)i = 1while i ≤ x.n and k > x.key[i]i = i + 1if i ≤ x.n and k == x.key[i]return (x, i) // 返回包含关键字的节点和关键字在节点中的位置elseif x.leafreturn NIL // 关键字不在树中else DISK-READ(x, c[i]) // 读取子节点return B-TREE-SEARCH(x.c[i], k) // 递归搜索子树

2. 插入(B-TREE-INSERT)

向B树中插入关键字的过程相对复杂,因为需要维护B树的性质。当向满节点插入新关键字时,需要进行分裂操作。以下是B树插入操作的伪代码框架:

B-TREE-INSERT(T, k)r = T.rootif r.n == 2t - 1 // 根节点满了s = ALLOCATE-NODE() // 分配新节点作为根节点的子节点T.root = ss.leaf = FALSEs.n = 0s.c[1] = rB-TREE-SPLIT-CHILD(s, 1) // 分裂根节点B-TREE-INSERT-NONFULL(s, k) // 向非满的新根节点插入关键字elseB-TREE-INSERT-NONFULL(r, k) // 直接向根节点插入关键字// 辅助过程,向非满节点插入关键字
B-TREE-INSERT-NONFULL(x, k)// ... 省略具体实现细节,包括分裂操作等 ...

3. 删除(B-TREE-DELETE)

从B树中删除关键字同样需要维护B树的性质。删除操作可能比插入操作更复杂,因为可能需要合并节点或重新调整关键字。以下是B树删除操作的一个简要描述:

  • 如果要删除的关键字在叶子节点中,直接删除并调整节点大小。
  • 如果要删除的关键字在内部节点中,找到其前驱或后继替代该关键字,并递归删除前驱或后继。
  • 如果删除操作导致节点大小低于最小要求,可能需要从相邻兄弟节点借调关键字,或者合并节点。

四、B树的C代码实现示例

由于完整的B树C代码实现较长且复杂,这里仅提供一个简化的框架和关键部分的代码示例,以便读者理解其实现思路。

首先,我们定义B树节点的结构体和一些辅助函数:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>#define MAX_KEYS 5
#define MAX_CHILDREN 6typedef int KeyType;typedef struct BTreeNode {int n; // 关键字数量KeyType keys[MAX_KEYS]; // 关键字数组struct BTreeNode *children[MAX_CHILDREN]; // 子节点指针数组bool is_leaf; // 是否为叶子节点
} BTreeNode;// 创建新节点
BTreeNode* createNode(bool is_leaf) {BTreeNode* node = (BTreeNode*)malloc(sizeof(BTreeNode));node->n = 0;node->is_leaf = is_leaf;for (int i = 0; i < MAX_CHILDREN; i++) {node->children[i] = NULL;}return node;
}// 分裂节点
void splitNode(BTreeNode* parent, int index, BTreeNode* child) {// 创建新节点,并分配中间关键字之后的元素BTreeNode* newNode = createNode(child->is_leaf);newNode->is_leaf = child->is_leaf;int mid = MAX_KEYS / 2;for (int i = mid + 1; i <= MAX_KEYS; i++) {newNode->keys[newNode->n] = child->keys[i];newNode->n++;}if (!child->is_leaf) {for (int i = mid + 1; i <= MAX_CHILDREN; i++) {newNode->children[newNode->n] = child->children[i];newNode->n++;}}// 将中间关键字上升到父节点parent->keys[index] = child->keys[mid];child->n = mid;// 插入新节点为父节点的一个子节点for (int i = parent->n; i > index; i--) {parent->keys[i] = parent->keys[i - 1];parent->children[i + 1] = parent->children[i];}parent->children[index + 1] = newNode;parent->n++;
}// 插入非满节点
void insertNonFull(BTreeNode* node, KeyType key) {int i = node->n - 1;// 找到新关键字的插入位置while (i >= 0 && key < node->keys[i]) {node->keys[i + 1] = node->keys[i];i--;}node->keys[i + 1] = key;node->n++;
}// B树插入操作
void insert(BTreeNode** root, KeyType key) {BTreeNode* node = *root;// 如果树为空,创建一个新节点if (node == NULL) {*root = createNode(true);insertNonFull(*root, key);return;}BTreeNode* current = node;BTreeNode* parent = NULL;int index = 0;// 查找插入位置while (!current->is_leaf) {index = 0;while (index < current->n && key > current->keys[index]) {index++;}parent = current;current = current->children[index];}// 插入到叶子节点insertNonFull(current, key);// 检查是否需要分裂while (current->n == MAX_KEYS + 1) {splitNode(parent, index, current);if (parent == NULL) {// 根节点满了,创建一个新的根节点*root = createNode(false);(*root)->children[0] = node;splitNode(*root, 0, node);return;}index = 0;while (parent->keys[index] < current->keys[0]) {index++;}current = parent;parent = parent->children[0] == current ? NULL : current->children[index + 1];}
}// 主函数,用于测试
int main() {BTreeNode* root = NULL;// 插入一些关键字进行测试insert(&root, 10);insert(&root, 20);insert(&root, 5);insert(&root, 15);insert(&root, 7);// ... 可以继续插入其他关键字进行测试 ...// 这里可以添加代码来遍历和打印B树的内容,以验证插入操作的正确性return 0;
}

这个示例代码实现了B树的插入操作,包括节点的分裂和根节点的提升。请注意,这个代码是为了教学目的而简化的,并没有处理所有的边界情况,也没有实现删除和查找等操作。在实际应用中,还需要进一步完善和优化。

五、总结

B树作为一种高效的数据结构,广泛应用于数据库和文件系统的索引中。其自平衡的特性保证了高效的插入、删除和搜索操作,尤其适用于磁盘等辅助存储器的存取系统。通过伪代码和C代码示例的介绍,我们可以更深入地理解B树的原理和实现细节。在实际应用中,根据具体需求和场景,可以对B树进行适当的变种和优化,以进一步提高其性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/831268.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯练习系统(算法训练)ALGO-953 混合积

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 众所周知&#xff0c;人人都在学习线性代数&#xff0c;既然都学过&#xff0c;那么解决本题应该很方便。   宇宙大战中&…

如何在postman上提交文件格式的数据

如何在postman上提交文件格式的数据 今天在写一个文件上传的功能接口时&#xff0c;想用postman进行提交&#xff0c;花了些时间才找到在postman提交文件格式的数据。记录一下吧&#xff01; 1.打开postman&#xff0c;选择POST提交方式&#xff0c;然后在Params那一行的Head…

数据分析--客户价值分析RFM(K-means聚类/轮廓系数)

原数据 import os import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn import metrics ### 数据抽取&#xff0c;读⼊数据 df pd.read_csv("customers1997.csv") #相对路径读取数据 print(df.info()) pr…

WPF之自定义绘图

1&#xff0c;创建自定义控件类 class CustomDrawnElement:FrameworkElement{public static readonly DependencyProperty BackgroundColorProperty;static CustomDrawnElement(){FrameworkPropertyMetadata meta new FrameworkPropertyMetadata(Colors.SkyBlue);meta.Affects…

Python-------实现人生重开模拟器

人生重开模拟器 代码展示:实现思路序言一、设置初始属性1.游戏标题2.属性初始化 二、设置角色性别三、设置角色出生点四、针对每一年的岁数&#xff0c;自动生成人生经历总结 代码展示: # 人生重开模拟器 import random import sys import timeprint(------------------------…

服务器IP选择

可以去https://ip.ping0.cc/查看IP的具体情况 1.IP位置--如果是国内用&#xff0c;国外服务器的话建议选择日本&#xff0c;香港这些比较好&#xff0c;因为它们离这里近&#xff0c;一般延时低&#xff08;在没有绕一圈的情况下&#xff09;。 不过GPT的话屏蔽了香港IP 2. 企…

GPT是什么?直观解释Transformer | 深度学习第5章 【3Blue1Brown 官方双语】

【官方双语】GPT是什么&#xff1f;直观解释Transformer | 深度学习第5章 0:00 - 预测&#xff0c;采样&#xff0c;重复&#xff1a;预训练/生成式/Transformer模型 3:03 - Transformer 的内部结构 6:36 - 本期总述 7:20 - 深度学习的大框架 12:27 - GPT的第一层&#xff1a;…

【论文浅尝】Large Language Models for Generative Information Extraction: A Survey

本文对生成式IE的LLM进行了全面的探索。使用两种分类法对现有的代表性方法进行分类: (1)众多IE子任务的分类法&#xff0c;旨在对可以使用llm单独或统一提取的不同类型的信息进行分类; (2)学习范式分类法&#xff0c;对利用llm生成IE的各种新方法进行分类。 Preliminaries o…

msmpi 高性能计算实现文件读取输入

【高性能计算】完美解决Windows下安装mpi环境并应用到VSCode中报错问题的方法_c:\program files (x86)\microsoft sdks\mpi\include/-CSDN博客 环境配置 然后跑这个代码测试即可 // 命令行参数&#xff1a; //mpiexec -n 9 "C:\Users\ASUS\Desktop\testMPI\MPIv2.exe&qu…

【氮化镓】GaN器件可靠性及市场前景概述

文章是关于氮化镓&#xff08;GaN&#xff09;场效应晶体管&#xff08;FET&#xff09;技术在空间应用中的可靠性、辐射效应和市场前景的概述。文章由Airbus Defence & Space的多位专家撰写&#xff0c;涵盖了GaN FET技术的多个关键方面&#xff0c;包括技术概述、可靠性问…

Find My无人机|苹果Find My技术与无人机结合,智能防丢,全球定位

无人机是利用无线电遥控设备和自备的程序控制装置操纵的不载人飞机&#xff0c;或者由车载计算机完全地或间歇地自主地操作。无人机按应用领域&#xff0c;可分为军用与民用。军用方面&#xff0c;无人机分为侦察机和靶机。民用方面&#xff0c;无人机行业应用&#xff0c;是无…

opencv基础篇 ——(十二)轮廓提取与绘制

opencv基础篇 ——&#xff08;十二&#xff09;轮廓提取与绘制 findContours轮廓提取 void void findContours( InputArray image, OutputArrayOfArrays contours,OutputArray hierarchy, int mode,int method, Point offset Point());功能介绍 cv::findContours 是 OpenC…

【python】商业数据聚类-回归数据分析可视化(源码+数据)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

ios CI/CD 持续集成 组件化专题四-(手动发布私有库-组件化搭建)

一 、创建私有索引库 1.1 、第一步 首先检查本地是否存在需要的私有索引库 pod repo list 例如&#xff1a;dp_base_ios_spec 在本地不存在该私有索引库 1.2 、第二步 在git下下创建一个新的库&#xff0c;这个库用来保存私有库的podspec文件&#xff0c;取名叫xxxSpec用以…

以更多架构核心专利,推进 SDS 产业创新创造

今天是第 24 个世界知识产权日&#xff0c;今年世界知识产权日活动的主题是&#xff1a;“知识产权和可持续发展目标&#xff1a;立足创新创造&#xff0c;构建共同未来。” 这也正是 XSKY 在软件定义存储领域的目标之一。以“数据常青”为使命的 XSKY&#xff0c;始终立足于软…

【MySQL | 第十篇】重新认识MySQL索引匹配过程

文章目录 10.重新认识MySQL索引匹配过程10.1匹配规则10.2举例&#xff1a;联合索引遇到范围查询&#xff08;>、<、between、like&#xff09;10.2.1例子一&#xff1a;>10.2.2例子二&#xff1a;>10.2.3例子三&#xff1a;between10.2.4例子四&#xff1a;like 10…

Unity SteamVR入门

概述 VR项目现在在当前已经是非常热门的技术&#xff0c;可以给玩家身临其境的感觉&#xff0c;接下来让我们学习这部分的内容吧&#xff01; SteamVR Input SteamVR绑定流程&#xff0c;在Windows窗口的点击SteamVR-input&#xff0c;图1&#xff0c;在这里可以选择你需要绑定…

SQL注入漏洞--报错/union/布尔盲注/时间盲注

之前介绍了数据库的基本操作&#xff0c;今天这篇文章就来实操SQL注入。 阅读本文前可以先看一下基本操作&#xff0c;有助于更换理解本文。。。 https://blog.csdn.net/weixin_60885144/article/details/138356410?spm1001.2014.3001.5502 what SQL---结构化查询语言---S…

探索AIGC技术:创新、挑战与责任

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f4d5;格言&#xff1a;那些在暗处执拗生长的花&#xff0c;终有一日会馥郁传香欢迎大家&#x1f44d;点赞✍评论⭐收藏 #如何看待AIGC技术&#xff1f; 目录 AIGC简单介绍 创新 责任 未来展望和挑战 AIGC简单介绍 A…

【Linux系统】守护进程

一.进程组&#xff0c;会话 PGID&#xff1a;进程组id&#xff0c;一条命令启动的所有进程及其子进程属于同一个进程组。一条指令中最先创建的进程就是组长&#xff0c;组id就是组长的PID。./启动的SID&#xff1a;会话id&#xff0c;每次登录Linux&#xff0c;操作系统给登录的…