当前位置: 首页 > news >正文

B树的实现:代码示例与解析

B树的实现:代码示例与解析

引言

B树是一种自平衡的树数据结构,广泛应用于文件系统和数据库系统中。它是一种多路搜索树,旨在保持数据有序并允许高效的查找、插入和删除操作。本文将深入探讨B树的实现,提供完整的代码示例和详细的解析。

B树的基本概念

定义

B树是一种平衡的多路搜索树,其定义如下:

  • 每个节点最多有m个子节点(m称为B树的阶)。
  • 除根节点外,每个节点至少有⌈m/2⌉个子节点。
  • 每个节点存储k-1个关键字,并且这些关键字按照从小到大的顺序存储。
  • 关键字将子节点分隔成k个区间,节点的子节点树包含的关键字数目符合关键字分隔的区间。

性质

  • 根节点至少有两个子节点,除非它是叶节点。
  • 所有叶子节点都位于同一层。
  • 节点的关键字将子节点的关键字分隔成区间,这些区间分别在节点的左子树和右子树中。

操作

B树的基本操作包括查找、插入和删除。每个操作都涉及节点的分裂和合并,以保持树的平衡。

B树的实现

下面我们使用Python来实现B树,并提供详细的代码解析。

B树节点类

首先,我们定义一个B树节点类BTreeNode,它包含基本的属性和方法:

class BTreeNode:def __init__(self, t, leaf=False):self.t = t  # 最小度数self.leaf = leaf  # 是否为叶子节点self.keys = []  # 存储关键字self.children = []  # 存储子节点def insert_non_full(self, key):i = len(self.keys) - 1if self.leaf:# 在叶子节点中插入新关键字self.keys.append(None)while i >= 0 and self.keys[i] > key:self.keys[i + 1] = self.keys[i]i -= 1self.keys[i + 1] = keyelse:# 在非叶子节点中插入新关键字while i >= 0 and self.keys[i] > key:i -= 1if len(self.children[i + 1].keys) == 2 * self.t - 1:self.split_child(i + 1)if self.keys[i + 1] < key:i += 1self.children[i + 1].insert_non_full(key)def split_child(self, i):t = self.ty = self.children[i]z = BTreeNode(t, y.leaf)self.children.insert(i + 1, z)self.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)]

B树类

接下来,我们定义B树类BTree,它包含树的根节点和基本的树操作:

class BTree:def __init__(self, t):self.t = t  # 最小度数self.root = BTreeNode(t, True)def insert(self, key):root = self.rootif len(root.keys) == 2 * self.t - 1:s = BTreeNode(self.t, False)s.children.insert(0, root)s.split_child(0)i = 0if s.keys[0] < key:i += 1s.children[i].insert_non_full(key)self.root = selse:root.insert_non_full(key)def search(self, key, node=None):if node is None:node = self.rooti = 0while i < len(node.keys) and key > node.keys[i]:i += 1if i < len(node.keys) and key == node.keys[i]:return nodeelif node.leaf:return Noneelse:return self.search(key, node.children[i])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 = Nonedef _delete(self, node, key):t = self.tif node is None:returnidx = 0while idx < len(node.keys) and node.keys[idx] < key:idx += 1if idx < len(node.keys) and node.keys[idx] == key:if node.leaf:node.keys.pop(idx)else:if len(node.children[idx].keys) >= t:pred = self.get_pred(node, idx)node.keys[idx] = predself._delete(node.children[idx], pred)elif len(node.children[idx + 1].keys) >= t:succ = self.get_succ(node, idx)node.keys[idx] = succself._delete(node.children[idx + 1], succ)else:self.merge(node, idx)self._delete(node.children[idx], key)else:if node.leaf:returnflag = idx == len(node.keys)if len(node.children[idx].keys) < t:self.fill(node, idx)if flag and idx > len(node.keys):self._delete(node.children[idx - 1], key)else:self._delete(node.children[idx], key)def get_pred(self, node, idx):current = node.children[idx]while not current.leaf:current = current.children[-1]return current.keys[-1]def get_succ(self, node, idx):current = node.children[idx + 1]while not current.leaf:current = current.children[0]return current.keys[0]def merge(self, node, idx):child = node.children[idx]sibling = node.children[idx + 1]child.keys.append(node.keys[idx])child.keys.extend(sibling.keys)if not child.leaf:child.children.extend(sibling.children)node.keys.pop(idx)node.children.pop(idx + 1)def fill(self, node, idx):t = self.tif idx != 0 and len(node.children[idx - 1].keys) >= t:self.borrow_from_prev(node, idx)elif idx != len(node.keys) and len(node.children[idx + 1].keys) >= t:self.borrow_from_next(node, idx)else:if idx != len(node.keys):self.merge(node, idx)else:self.merge(node, idx - 1)def borrow_from_prev(self, node, idx):child = node.children[idx]sibling = node.children[idx - 1]child.keys.insert(0, node.keys[idx - 1])if not child.leaf:child.children.insert(0, sibling.children.pop())node.keys[idx - 1] = sibling.keys.pop()def borrow_from_next(self, node, idx):child = node.children[idx]sibling = node.children[idx + 1]child.keys.append(node.keys[idx])if not child.leaf:child.children.append(sibling.children.pop(0))node.keys[idx] = sibling.keys.pop(0)

代码解析

BTreeNode 类

BTreeNode 类表示 B 树的节点,其属性包括:

  • t: B 树的最小度数。
  • leaf: 一个布尔值,表示节点是否为叶节点。
  • keys: 一个列表,存储节点的关键字。
  • children: 一个列表,存储节点的子节点。

该类的方法包括:

  • insert_non_full(key): 在非满节点中插入关键字。
  • split_child(i): 分裂满子节点。

BTree 类

BTree 类表示整个 B 树,其属性包括:

  • t: B 树的最小度数。
  • root: B 树的根节点。

该类的方法包括:

  • insert(key): 插入关键字。
  • search(key, node=None): 查找关键字。
  • delete(key): 删除关键字。
  • _delete(node, key): 辅助删除方法。
  • get_pred(node, idx): 获取前驱关键字。
  • get_succ(node, idx): 获取后继关键字。
  • merge(node, idx): 合并节点。
  • fill(node, idx): 填充节点。
  • borrow_from_prev(node, idx): 从前一个兄弟节点借一个关键字。
  • `borrow_from_next(node,

idx)`: 从下一个兄弟节点借一个关键字。

示例代码

下面的示例代码展示了如何使用上述 B 树实现进行插入、查找和删除操作:

if __name__ == "__main__":btree = BTree(3)# 插入关键字keys_to_insert = [10, 20, 5, 6, 12, 30, 7, 17]for key in keys_to_insert:btree.insert(key)# 查找关键字key_to_search = 6result = btree.search(key_to_search)if result:print(f"关键字 {key_to_search} 找到在节点: {result.keys}")else:print(f"关键字 {key_to_search} 不存在")# 删除关键字keys_to_delete = [6, 13, 7]for key in keys_to_delete:btree.delete(key)print(f"删除关键字 {key} 后的树结构:")# 打印树结构print_tree(btree.root)

打印树结构

为了更好地理解 B 树的结构,我们可以编写一个函数来打印树结构:

def print_tree(node, level=0):print("Level", level, ":", node.keys)level += 1for child in node.children:print_tree(child, level)

结论

本文详细介绍了 B 树的基本概念、实现以及代码示例。通过 Python 实现 B 树并提供相关操作的代码解析,我们可以更好地理解 B 树的工作原理和应用场景。B 树是一种非常重要的数据结构,其高效的查找、插入和删除操作使其在数据库系统和文件系统中得到了广泛应用。希望本文能够帮助读者更好地掌握 B 树的实现与应用。

相关文章:

B树的实现:代码示例与解析

B树的实现&#xff1a;代码示例与解析 引言 B树是一种自平衡的树数据结构&#xff0c;广泛应用于文件系统和数据库系统中。它是一种多路搜索树&#xff0c;旨在保持数据有序并允许高效的查找、插入和删除操作。本文将深入探讨B树的实现&#xff0c;提供完整的代码示例和详细的…...

HCIA总结

一、情景再现&#xff1a;ISP网络为学校提供了DNS服务&#xff0c;所以&#xff0c;DNS服务器驻留在ISP网络内&#xff0c;而不再学校网络内。DHCP服务器运行在学校网络的路由器上 小明拿了一台电脑&#xff0c;通过网线&#xff0c;接入到校园网内部。其目的是为了访问谷歌网站…...

软件测试_接口测试面试题

接口测试是软件测试中的重要环节&#xff0c;它主要验证系统不同模块之间的通信和数据交互是否正常。在软件开发过程中&#xff0c;各个模块之间的接口是实现功能的关键要素&#xff0c;因此对接口进行全面而准确的测试是确保系统稳定性和可靠性的关键步骤。 接口测试的核心目…...

C++初阶学习第五弹——类与对象(下)

类与对象&#xff08;上&#xff09;&#xff1a;C初阶学习第三弹——类与对象&#xff08;上&#xff09;-CSDN博客 类和对象&#xff08;中&#xff09;&#xff1a;C初阶学习第四弹——类与对象&#xff08;中&#xff09;-CSDN博客 一.赋值运算符重载 1.1 运算符重载 C为…...

最低工资标准数据(2001-2023年不等)、省市县,整理好的面板数据(excel格式)

时间范围&#xff1a;2001-2022年 具体内容&#xff1a;一&#xff1a;最低工资数据标准时间&#xff1a;2012-2021包含指标&#xff1a; 省份城市/区县小时最低工资标准&#xff08;非全日制&#xff09;月最低工资标准实施日期 样例数据&#xff1a; 二&#xff1a;各省最低…...

计算机毕业设计选题推荐-戏曲文化体验系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...

【深度学习】CosyVoice,论文

CosyVoice_v1.pdf 文章目录 CosyVoice: A Scalable Multilingual Zero-shot Text-to-speech Synthesizer based on Supervised Semantic Tokens摘要1 引言2 CosyVoice: 使用监督语义标记的可扩展TTS模型2.1 用于语音的监督语义标记2.2 用于TTS的大型语言模型2.3 最优传输条件流…...

PHP8.3.9安装记录,Phpmyadmin访问提示缺少mysqli

ubuntu 22.0.4 腾讯云主机 下载好依赖 sudo apt update sudo apt install -y build-essential libxml2-dev libssl-dev libcurl4-openssl-dev pkg-config libbz2-dev libreadline-dev libicu-dev libsqlite3-dev libwebp-dev 下载php8.3.9安装包 nullhttps://www.php.net/d…...

[译] 深入浅出Rust基金会

本篇是对 RustConf 2023中的Rust Foundation: Demystified这一视频的翻译与整理, 过程中为符合中文惯用表达有适当删改, 版权归原作者所有. 大家好,我是Sage Griffin,我的代词是they/them。我今天来这里是要谈谈Rust基金会。 要了解基金会实际做什么,我们需要理解美国国内税收…...

Postman:API开发与测试的强大伴侣

在当今的数字化时代&#xff0c;API&#xff08;应用程序编程接口&#xff09;已成为不同软件系统之间通信的桥梁&#xff0c;它们如同数字世界的“翻译官”&#xff0c;使得数据和服务能够在不同的平台和应用程序之间无缝流动。然而&#xff0c;API的开发、测试和维护并非易事…...

Web应用的视界革命:WebKit支持屏幕方向API的深度解析

Web应用的视界革命&#xff1a;WebKit支持屏幕方向API的深度解析 在现代Web应用开发中&#xff0c;屏幕方向的适应性是一个重要的考虑因素。屏幕方向API&#xff08;Screen Orientation API&#xff09;提供了一种方法&#xff0c;允许Web应用知道并响应屏幕的方向变化&#x…...

【前端】一文带你了解 CSS

文章目录 1. CSS 是什么2. CSS 引入方式2.1 内部样式2.2 外部样式2.3 内联样式 3. CSS 常见选择器3.1 基础选择器3.1.1 标签选择器3.1.2 类选择器3.1.3 id 选择器3.1.4 通配符选择器 3.2 复合选择器3.2.1 后代选择器 4. CSS 常用属性4.1 字体相关4.2 文本相关4.3 背景相关4.4 设…...

IT服务运营管理中的关键考核指标

IT服务运营过程中常见的关键考核指标体现在人员、技术、资源、过程、质量等要素中&#xff0c;下面把常见的考核项目、计算方式、考核周期罗列如下&#xff0c;本考核指标主要用于对IT服务运营单位或部门的考核。 IT服务运营管理关键考核指标 要素考核项目计算方式常见考核周期…...

复习C语言从源文件.C到二进制.bin或可执行文件.exe文件的流程

...

如何恢复硬盘里删除的数据?硬盘数据恢复真的可靠吗?2024最新解答!

在日常的计算机使用中&#xff0c;我们时常会不小心删除硬盘中的重要数据&#xff0c;这时候&#xff0c;数据恢复就显得尤为重要。本文将介绍几种恢复硬盘里删除数据的方法&#xff0c;并探讨硬盘数据恢复的可靠性&#xff0c;提供2024年的最新解答。 一、什么是电脑硬盘&…...

Android Studio的新界面,怎么切换回老界面

将勾选的 Enable new UI 取消掉即可...

怎么用U盘重装系统

在使用电脑的过程中&#xff0c;难免会遇到系统故障、运行缓慢等问题。当这些问题严重影响使用电脑的体验时&#xff0c;重装系统往往是一个有效的解决办法。用U盘重装系统是一种简单快捷的方法&#xff0c;本文将详细介绍如何使用U盘来重装系统&#xff0c;帮助大家轻松完成这…...

Spring事件快速上手

文章目录 应用场景核心接口使用步骤异步事件事件排序 Spring 事件&#xff08;Application Event&#xff09;是 Spring 框架中实现观察者模式的一种方式&#xff0c;可以通过发布者和监听器来处理事件&#xff0c;常用于类之间解耦合、异步操作。 观察者模式&#xff1a;观察者…...

java算法递归算法练习-数组之和

简单找个题目练习一下递归算法&#xff0c;输入一组数组&#xff0c;使用递归的方法计算数组之和。其实这个题目&#xff0c;用循环的方式也很简单就能解决&#xff0c;直接循环遍历一下相加就行了&#xff0c;但是我们用来练习一下递归。 先来找基线条件和递归条件 基线条件…...

在kdevelop中运行程序并调试

补充前序知识&#xff1a; 1.CMakeLists.txt文件中&#xff0c;如下图&#xff0c;第一行生成的是静态库文件&#xff08;我们前一讲所使用的&#xff09;&#xff0c;第二行是动态库文件。 静态库与动态库&#xff1a; 静态库&#xff08;Static Libraries&#xff09; 定义…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统&#xff0c;它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间&#xff0c;使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的&#xff0c;要在 …...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...