数据结构之B树:深入了解与应用
目录
1. B树的基本概念
1.1 B树的定义
1.2 B树的性质
1.3 B树的阶
2. B树的结构
2.1 节点结构
2.2 节点分裂
2.3 节点合并
3. B树的基本操作
3.1 搜索
3.2 插入
3.3 删除
4. B树的应用
4.1 数据库索引
4.2 文件系统
4.3 内存管理
5. B树的优势和局限
5.1 优势
5.2 局限
6. B树的实现与示例
6.1 B树的插入操作示例
6.2 B树的搜索操作示例
6.3 B树的删除操作示例
7. 结论
B树(B-Tree)是一种自平衡的树数据结构,广泛应用于数据库和文件系统中,用于高效地执行插入、删除和搜索操作。本文将详细介绍B树的概念、结构、操作及其应用,并通过实例和图示帮助读者深入理解B树的工作原理和优势。
1. B树的基本概念
1.1 B树的定义
B树是一种平衡多路查找树,具有以下特点:
- 每个节点包含多个关键字(Keys)和子节点(Children)。
- 节点中的关键字按升序排列。
- 每个节点的子节点数量与其关键字数量有严格关系:假设一个节点包含 n 个关键字,那么它必须有 n+1 个子节点。
- 所有叶子节点在同一层次上,保证了树的平衡性。
1.2 B树的性质
B树的性质包括:
- 根节点至少有两个子节点(除非是空树)。
- 每个节点最多有 m 个子节点(m 是B树的阶,m >= 2)。
- 每个节点(除根节点和叶子节点)至少有 ⌈m/2⌉ 个子节点。
- 所有叶子节点都在同一层次上。
1.3 B树的阶
B树的阶(Order)是一个关键参数,表示每个节点的最大子节点数量。常见的B树阶包括B-Tree、B+-Tree、B*-Tree等,具体的结构和操作可能略有不同,但基本思想是一致的。
2. B树的结构
2.1 节点结构
每个节点包含以下部分:
- 关键字数组(Keys):按升序排列的关键字列表。
- 子节点指针数组(Children):指向子节点的指针列表,数量比关键字多1。
- 节点属性(Properties):包括当前关键字数量、是否为叶子节点等。
2.2 节点分裂
当节点中的关键字数量达到最大值时,需要进行分裂操作,将节点分为两个部分,并将中间关键字提升到父节点中。这个过程保证了B树的平衡性。
2.3 节点合并
当节点中的关键字数量低于最小值时,需要进行合并操作,将关键字和子节点与相邻节点合并,以维持B树的平衡性。
3. B树的基本操作
3.1 搜索
B树的搜索操作类似于二分查找,按以下步骤进行:
- 从根节点开始,逐个比较关键字,找到目标关键字或确定目标关键字所在的子节点。
- 递归地在子节点中搜索,直到找到目标关键字或到达叶子节点。
3.2 插入
B树的插入操作包括以下步骤:
- 从根节点开始,找到插入位置的叶子节点。
- 将新关键字插入叶子节点,保持关键字的升序排列。
- 如果节点关键字数量超过最大值,进行节点分裂,并将中间关键字提升到父节点。
- 递归处理分裂的父节点,直到树恢复平衡。
3.3 删除
B树的删除操作相对复杂,包括以下步骤:
- 找到要删除的关键字所在的节点。
- 如果关键字在叶子节点中,直接删除。
- 如果关键字在内部节点中,用前驱或后继关键字替换,并在子树中删除前驱或后继关键字。
- 如果节点关键字数量低于最小值,进行节点合并或关键字重分配,保持树的平衡性。
4. B树的应用
4.1 数据库索引
B树广泛应用于数据库索引中,如B-Tree索引、B+-Tree索引等。B树结构保证了索引的平衡性和高效性,支持快速插入、删除和搜索操作,适用于大规模数据管理。
4.2 文件系统
B树也应用于文件系统中,如NTFS和HFS+等。通过B树结构,可以高效管理文件目录和元数据,实现快速文件访问和操作。
4.3 内存管理
在内存管理中,B树用于实现分页和虚拟内存映射,通过高效的查找和管理算法,优化内存分配和访问性能。
5. B树的优势和局限
5.1 优势
- 平衡性: B树的所有叶子节点在同一层次上,保证了树的平衡性。
- 高效性: B树的搜索、插入和删除操作都在O(log n)时间复杂度内完成,适合大规模数据管理。
- 灵活性: B树支持多种阶和变种(如B+-Tree、B*-Tree等),可以根据具体应用需求调整结构和参数。
5.2 局限
- 空间复杂度: B树需要额外的指针和属性存储,可能增加内存开销。
- 节点分裂和合并: 插入和删除操作可能涉及节点分裂和合并,增加了操作复杂度和开销。
6. B树的实现与示例
6.1 B树的插入操作示例
以下是一个B树插入操作的示例,演示了插入关键字和节点分裂的过程:
class BTreeNode:def __init__(self, leaf=False):self.leaf = leafself.keys = []self.children = []class BTree:def __init__(self, t):self.root = BTreeNode(True)self.t = t # 最小度数def insert(self, key):root = self.rootif len(root.keys) == 2 * self.t - 1:temp = BTreeNode()self.root = temptemp.children.insert(0, root)self._split_child(temp, 0)self._insert_non_full(temp, key)else:self._insert_non_full(root, key)def _split_child(self, node, i):t = self.ty = node.children[i]z = BTreeNode(y.leaf)node.children.insert(i + 1, z)node.keys.insert(i, y.keys[t - 1])z.keys = y.keys[t: (2 * t - 1)]y.keys = y.keys[0: (t - 1)]if not y.leaf:z.children = y.children[t: (2 * t)]y.children = y.children[0: (t - 1)]def _insert_non_full(self, node, key):i = len(node.keys) - 1if node.leaf:node.keys.append(0)while i >= 0 and key < node.keys[i]:node.keys[i + 1] = node.keys[i]i -= 1node.keys[i + 1] = keyelse:while i >= 0 and key < node.keys[i]:i -= 1i += 1if len(node.children[i].keys) == 2 * self.t - 1:self._split_child(node, i)if key > node.keys[i]:i += 1self._insert_non_full(node.children[i], key)
6.2 B树的搜索操作示例
以下是一个B树搜索操作的示例,演示了在B树中查找关键字的过程:
def search(self, node, key):i = 0while i < len(node.keys) and key > node.keys[i]:i += 1if i < len(node.keys) and key == node.keys[i]:return (node, i)elif node.leaf:return Noneelse:return self.search(node.children[i], key)
6.3 B树的删除操作示例
以下是一个B树删除操作的示例,演示了在B树中删除关键字的过程:
def delete(self, key):self._delete(self.root, key)if len(self.root.keys) == 0:if not self.root.leaf:self.root = self.root.children[0]else:self.root = BTreeNode(True)def _delete(self, node, key):t = self.ti = 0while i < len(node.keys) and key > node.keys[i]:i += 1if i < len(node.keys) and key == node.keys[i]:if node.leaf:node.keys.pop(i)else:self._delete_internal_node(node, key, i)elif node.leaf:returnelse:self._delete(node.children[i], key)if len(node.children[i].keys) < t - 1:self._fix(node, i)def _delete_internal_node(self, node, key, i):t = self.tif len(node.children[i].keys) >= t:pred = self._get_predecessor(node.children[i])node.keys[i] = predself._delete(node.children[i], pred)elif len(node.children[i + 1].keys) >= t:succ = self._get_successor(node.children[i + 1])node.keys[i] = succself._delete(node.children[i + 1], succ)else:self._merge(node, i)self._delete(node.children[i], key)def _get_predecessor(self, node):if node.leaf:return node.keys[-1]else:return self._get_predecessor(node.children[-1])def _get_successor(self, node):if node.leaf:return node.keys[0]else:return self._get_successor(node.children[0])def _merge(self, node, i):child = node.children[i]sibling = node.children[i + 1]child.keys.append(node.keys.pop(i))child.keys.extend(sibling.keys)if not child.leaf:child.children.extend(sibling.children)node.children.pop(i + 1)def _fix(self, node, i):t = self.tif i != 0 and len(node.children[i - 1].keys) >= t:self._borrow_from_prev(node, i)elif i != len(node.children) - 1 and len(node.children[i + 1].keys) >= t:self._borrow_from_next(node, i)else:if i != len(node.children) - 1:self._merge(node, i)else:self._merge(node, i - 1)def _borrow_from_prev(self, node, i):child = node.children[i]sibling = node.children[i - 1]child.keys.insert(0, node.keys[i - 1])if not child.leaf:child.children.insert(0, sibling.children.pop())node.keys[i - 1] = sibling.keys.pop()def _borrow_from_next(self, node, i):child = node.children[i]sibling = node.children[i + 1]child.keys.append(node.keys[i])if not child.leaf:child.children.append(sibling.children.pop(0))node.keys[i] = sibling.keys.pop(0)
7. 结论
B树作为一种高效的多路查找树,广泛应用于数据库、文件系统和内存管理等领域。通过深入理解B树的结构和操作,读者可以更好地应用B树来优化数据管理和查询性能。本文详细介绍了B树的基本概念、结构、操作及其应用,并提供了具体的实现示例,帮助读者全面掌握B树的理论和实践。
相关文章:
数据结构之B树:深入了解与应用
目录 1. B树的基本概念 1.1 B树的定义 1.2 B树的性质 1.3 B树的阶 2. B树的结构 2.1 节点结构 2.2 节点分裂 2.3 节点合并 3. B树的基本操作 3.1 搜索 3.2 插入 3.3 删除 4. B树的应用 4.1 数据库索引 4.2 文件系统 4.3 内存管理 5. B树的优势和局限 5.1 优势…...

Tensorflow入门实战 T06-Vgg16 明星识别
目录 1、前言 2、 完整代码 3、运行过程结果 4、遇到的问题 5、小结 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项目定制 1、前言 这周主要是使用VGG16模型,完成明星照片识别。 2、 完整代…...

SpringBoot 3.3.1 + Minio 实现极速上传和预览模式
统一版本管理 <properties><minio.version>8.5.10</minio.version><aws.version>1.12.737</aws.version><hutool.version>5.8.28</hutool.version> </properties><!--minio --> <dependency><groupId>io.m…...
Linux: network: 丢包分析的另一个途径 tracing
丢包的另一个思路,内核里有些counter的计数,记录的不准确。这个时候怎么办?就需要使用另外一个方式:/sys/kernel/debug/tracing/event/skb/kfree_skb 的跟踪功能。这个算是对counter的一个补充,可以拿来做统计分析使用…...

【保姆级教程+配置源码】在VScode配置C/C++环境
目录 一、下载VScode 1. 在官网直接下载安装即可 2. 安装中文插件 二、下载C语言编译器MinGW-W64 三、配置编译器环境变量 1. 解压下载的压缩包,复制该文件夹下bin目录所在地址 2. 在电脑搜索环境变量并打开 3. 点击环境变量→选择系统变量里的Path→点击编…...

Qt creator实现一个简单计算器
目录 1 界面设计 2 思路简介 3 代码 目录 1 界面设计 2 思路简介 3 代码 3.1 widget.h 3.2 widget.c 4 完整代码 在这里主要记载了如何使用Qt creator完成一个计算器的功能。该计算器可以实现正常的加减乘除以及括号操作,能实现简单的计算器功能。 1 界…...

Java代码基础算法练习-计算被 3 或 5 整除数之和-2024.06.29
任务描述: 计算 1 到 n 之间能够被 3 或者 5 整除的数之和。 解决思路: 输入的数字为 for 循环总次数,每次循环就以当前的 i 进行 3、5 的取余操作,都成立计入总数sum中,循环结束,输出 sum 的值 代码示例&…...
Socket编程详解(二)核心代码讲解
本文对代码的讲解基于上一篇博客 快速链接 Socket编程详解(一)服务端与客户端的双向对话 小试牛刀1:委托声明的关键字和委托方法使用的方法名是不一样的名称 可读性:有时,委托的名称可能描述了它的用途或它在哪里被…...

(项目实战)聚合支付系统开发环境搭建-基于VMware17安装Centos7.9
1 开发环境介绍 dtpay聚合支付系统和ecard预付卡系统,服务端部署在Linux环境。后续的开发环境,生产环境都是基于Linux进行搭建,系统使用到的相关中间件(RocketMQ,Redis,Nginx等),配置中心Nacos,数据库MySQ…...

Python现在可以在线编程了!
你好,我是郭震 1 在线编程 在线编程好处: 1 无需安装和配置环境: 在线编程平台不需要用户在本地安装任何软件或配置开发环境。这对初学者和那些希望快速上手进行编程的人非常有利。 2 跨平台兼容性: 这些平台可以在任何具有互联网连接的设备上使用&#…...

ThreadPoolExecutor线程池创建线程
线程池介绍 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源&#…...
畅谈GPT-5
前言 ChatGBT(Chat Generative Bidirectional Transformer)是一种基于自然语言处理技术的对话系统,它的出现是人工智能和自然语言处理技术发展的必然趋势。随着技术的更新和进步,GPT也迎来了一代代的更新迭代。 1.GPT的回顾 1.1 GPT-3的介绍 GPT-3(Gen…...

石家庄高校大学智能制造实验室数字孪生可视化系统平台项目验收
智能制造作为未来制造业的发展方向,已成为各国竞相发展的重点领域。石家庄高校大学智能制造实验室积极响应国家发展战略,结合自身优势,决定引进数字孪生技术,构建一个集教学、科研、生产于一体的可视化系统平台。 数字孪生可视化…...

WLAN 4-Way Handshake如何生成GTK?
关于Wi-Fi的加密认证过程,可以参考如下链接,今天我们来理解如何生成GTK。 WLAN数据加密机制_tls加密wifi-CSDN博客 1 GTK GTK(Group Temporal Key)是由AP通过GMK生成,长度为128位,并在四次握手的第三步中…...
Qt/C++模拟鼠标键盘输入
1、控制鼠标移动 (1)Qt方案 QScreen* sc QGuiApplication::primaryScreen(); QCursor* c new QCursor(); int deltaX 10; int deltaY 10; c->setPos(sc, c->pos().x() deltaX, c->pos().y() deltaY);(2)Windows原…...

OpenGL3.3_C++_Windows(22)
材质: 决定物体在渲染过程中最终视觉呈现的关键因素之一,它通过一系列光学(投光物)和物理参数(反光度,反照率、金属度,折射率……)准确模拟现实世界中的材料特性,从而增…...

electron-builder 打包过慢解决
报错内容如下 > 6-241.0.0 build > electron-builder • electron-builder version24.13.3 os10.0.22631 • loaded configuration filepackage.json ("build" field) • writing effective config filedist\builder-effective-config.yaml • pack…...
leetcode226反转二叉树
本文主要讲解反转二叉树的要点与细节,按照步骤思考更方便理解 c和java代码如下,末尾 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 具体要点: 1. 首先我们要理解题意, 反转二叉树具体…...

【自然语言处理系列】探索NLP:使用Spacy进行分词、分句、词性标注和命名实体识别,并以《傲慢与偏见》与全球恐怖活动两个实例文本进行分析
本文深入探讨了scaPy库在文本分析和数据可视化方面的应用。首先,我们通过简单的文本处理任务,如分词和分句,来展示scaPy的基本功能。接着,我们利用scaPy的命名实体识别和词性标注功能,分析了Jane Austen的经典小说《傲…...
【Rust】function和methed的区别
文章目录 functionmethedAssociated Functions 参考资料 一句话总结: function和methed很多都是相同的。 不同点在于: methed定义在结构体里面,并且它的第一个参数肯定是self,代表结构体实例。方法需要用实例名.方法名调用当然结…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...