效率高的B树系列

文章目录

  • 前言
  • B树
    • 概念
    • 性质
    • 插入数据分析
    • 代码实现
    • 性能分析
  • B+树
    • 概念
    • 特性
    • 插入数据分析
    • 应用
  • B*树
    • 概念
    • B*树的分裂
  • 总结
    • B树系列的区别
    • B树系列对比哈希和平衡搜索树

前言

前面我们所学习到的数据结构,只能用来存储少量的数据,因为内存大小是非常有限的,一般情况下,也就几十个G,面对海量数据时,也就只能加载少部分数据到内存,其它的都存在磁盘,而与磁盘交换,即IO,速度是非常慢的

如下图,以二叉平衡树为例,树节点存的是磁盘中数据的地址,当数据量非常庞大时,这棵树的高度也就非常高,而内存中,为了存储更多的数据,每个节点就不存储关键字,只存储磁盘地址,所以可能每到一层,就需要进行一次磁盘IO,所以就需要进行高度次磁盘IO,效率很低
在这里插入图片描述
而使用哈希表,效率虽然是O(1),但在一些极端场景下,某个位置冲突很多,导致访问次数剧增

B树

概念

为了解决前面所说的问题,R.Bayer和E.mccreight提出了B树,B树是一棵多叉平衡搜索树,如下图,B树中一个节点,存储多个关键字,这里的关键字一般也是磁盘地址,磁盘查找效率低,在于寻址慢,而B树,从两方面解决二叉平衡树的问题,第一个是从二叉变多叉,树的高度也就被降低了很多,第二个是每个节点存储多个关键字及映射的值
在这里插入图片描述

性质

一颗M阶(m>2)的B树,是一颗平衡的M路平衡搜索树,可以是空树,性质如下:

根节点至少有两个孩子

每个分支节点都包含k-1个关键字和k个孩子,ceil(m/2) <= k <= m,ceil是向上取整函数

每个叶子节点都包含k-1个关键字,ceil(m/2) <= k <= m

所有的叶子节点都在同一层

每个节点中的关键字从小到大排列,节点中k-1个元素正好是k个孩子包含的元素的值域划分

每个节点的结构为:(n,A0,K1,A1,K2,A2,… ,Kn,An),Ki(1<=i<=n)为关键字,且Ki < Ki + 1 (1<=i<=n-1),Ai(0<=i<=n)为指向子树根节点的指针,且Ai所指子树所有节点中的关键字均小于Ki + 1,n为节点中关键字的个数,满足ceil(m/2)-1<=n<=m-1

插入数据分析

为了简单起见,这里M=3,且将节点的孩子个数和关键字个数均在原来的基础上多加1个,如下图
在这里插入图片描述
插入53、139、75,如下图,按照类似插入排序的方式,保持关键字有序
在这里插入图片描述
上面关键字已经满了,就需要进行分裂,将关键字中的中位数提出来插入到新建的父节点中,同时新建一个兄弟节点,将一半关键字分给兄弟节点,并将对应的一半孩子节点也分给兄弟,最后父节点指向两个孩子节点
在这里插入图片描述
插入49,145,从根节点开始查找,比它小,就在左边节点,比它大就往后继续走
在这里插入图片描述
插入36
在这里插入图片描述
插入101
在这里插入图片描述
综上所述,可以看出,B树的插入过程,是一个自左向右,自底向上的过程,当节点关键字满了就分裂,然后往上插入节点,再满,就再分裂,依次类推

代码实现

为了便于分裂,多给了一个孩子和一个关键字,同时给一个父节点指针,便于后面插入节点
在这里插入图片描述
给定一个根节点
在这里插入图片描述
在这里插入图片描述
查找关键字,如果待插入的关键字小于当前节点的关键字,就直接跳到当前节点的孩子节点;如果是大于当前节点的关键字,就继续往后走;否则,要找的关键字就在当前节点,返回该节点和关键字在当前节点中的下标;找完叶子节点都没有找到,就说明不存在,返回最后找的叶子节点和-1的下标的键值对
在这里插入图片描述
插入关键字,类似于插入排序,值得注意的是,孩子节点的位置也需要变动,同时,如果有孩子节点,还需要指向孩子节点,而孩子节点指向父亲
在这里插入图片描述
插入数据操作,首先,要判断是不是第一个关键字,如果是,就创建一个新节点,并将关键字插入其中即可
在这里插入图片描述
查找当前关键字是否存在,存在就直接返回即可
在这里插入图片描述
因为可能会涉及自底向上的连续分裂,所以需要多加一层死循环,如果插入关键字后的节点没有满,就直接返回即可
在这里插入图片描述
分裂节点,首先要找到节点的中位数的下标,然后创建兄弟节点,分一半关键字和孩子节点给兄弟,清空原节点已经不存在的关键字和孩子节点,最后更新两个节点的关键字个数
在这里插入图片描述
当前节点没有根节点,就创建新的根节点,然后将原节点关键字的中位数插入到根节点,同时,根节点指向这两个孩子节点,最后两个孩子节点指向父亲节点;有根节点,就将key更新为中位数,原节点更新为它的父节点,等待下次循环插入关键字
在这里插入图片描述
验证这棵树是否正确,可以采用中序遍历的方式,查看是否有序即可,不过,这无法判断指向父节点的指针的指向是否正确,这就需要通过监视窗口去看了
在这里插入图片描述

性能分析

如下图,磁盘IO的次数近似为以M为底,N为真数的对数,其中,M为树的度,N为关键字的个数
在这里插入图片描述

B+树

概念

B+树是B树的变形,规则和B树基本类似,但在B树的基础上进行了一些优化,如下所示:

分支节点的子树指针与关键字个数相同

分支节点的子树指针p[i]指向的关键字值大小在[k[i],k[i+1]]之间

所有叶子节点增加一个链接指针链接在一起

所有关键字及其映射的数据都在叶子节点出现

如下图,就是一颗B+树,分支节点与叶子节点有重复的值,分支节点存的是叶子节点的索引;父节点中存的是孩子节点中的最小值做索引
在这里插入图片描述

特性

所有关键字都出现在叶子节点的链表中,且链表中的节点都是有序的

不可能在分支节点中命中

分支节点相对于是叶子节点的索引,叶子节点才是存储数据的数据层

插入数据分析

插入53,139,75,49,145,36,101
在这里插入图片描述

应用

B+树应用于数据库索引

B*树

概念

B*树是B+树的变形,在非根和非叶子节点上,再增加指向兄弟节点的指针,如下图
在这里插入图片描述

B*树的分裂

当一个节点满时,如果它的下一个兄弟节点未满,则将一部分数据移到兄弟节点中,再在原节点插入关键字,最后修改父节点中兄弟节点的关键字;如果兄弟也满了,则在原节点与父节点之间增加新节点,并各复制1/3的数据到新节点,最后在父节点增加新节点的指针

总结

B树系列的区别

B树:有序数组 + 平衡多叉树

B+树:有序数组链表 + 平衡多叉树

B*树:更丰满的,空间利用率更高的B+树

B树系列对比哈希和平衡搜索树

B树系列有一些隐形坏处:

空间利用率低,消耗高;

插入删除数据时,分裂和合并节点,必然要挪动数据

虽然高度更低,但在内存中而言,跟哈希和平衡搜索树是一个量级

结论:B树系列在内存中体现不出优势

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

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

相关文章

.ui文件相关

目录 ui类生成过程&#xff1a; 提问&#xff1a; 等以后自己熟练了用代码写这些样式内容&#xff0c;尽量用代码写&#xff0c;原因很简单&#xff1a; 用代码写的可以直接修改代码&#xff0c;但是在设计界面修改的东西&#xff0c;电脑没有QC这玩意&#xff0c;还真不好改…

Gitlab7.14 中文版安装教程

Gitlab7.14 中文版安装教程 注&#xff1a; 本教程由羞涩梦整理同步发布&#xff0c;本人技术分享站点&#xff1a;blog.hukanfa.com转发本文请备注原文链接&#xff0c;本文内容整理日期&#xff1a;2024-01-28csdn 博客名称&#xff1a;五维空间-影子&#xff0c;欢迎关注 …

JWT(JSON Web Token)详解以及在go-zero中配置的方法

目的 对用户进行身份认证和信息交换 RFC 7519 传统方式 通过session保存对话信息&#xff0c;服务端返回一个session id&#xff0c;用户保存这个id在cookie内&#xff0c;然后每次请求都传给服务端 局限性 对于服务器集群难以向每个服务器共享同一session jwt的方式是…

【vue】vue.config.js里面获取本机ip:

文章目录 一、效果&#xff1a;二、实现&#xff1a; 一、效果&#xff1a; 二、实现&#xff1a; const os require(os);function getLocalIpAddress() {const interfaces os.networkInterfaces();for (let key in interfaces) {const iface interfaces[key];for (let i …

第九节HarmonyOS 常用基础组件16-Blank

1、描述 空白填充组件&#xff0c;在容器主轴方向上&#xff0c;空白填充组件具有自动填充容器空余部分的能力。仅当父组件为Row/Column/Flex时生效。 2、接口 Blank(min?: number | string) 3、参数 参数名 参数类型 必填 描述 min number|string 否 空白填充组件…

数据分析入门指南:用 Python 开启数据之旅

文章目录 前言发现宝藏为什么选择 Python 进行数据分析&#xff1f;准备工作数据分析基础1. 数据加载2. 数据探索3. 数据清洗4. 数据可视化 探索更多可能性好书推荐总结 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客&#xff0c;方便日后回顾。…

成都直播产业园核心优势全面解读,入驻天府锋巢直播产业基地都有哪些好处?

一文讲清&#xff01;成都直播产业园核心优势全面解读 企业入驻天府锋巢直播产业基地能获得哪些好处&#xff1f; 锋巢资讯&#xff5e;又来了&#xff5e;&#xff5e;&#xff5e; 今天&#xff0c;将为您全面解读成都产业园重点特色产业服务&#xff08;上&#xff09; 什…

Android 13以上版本读写SD卡权限适配

如题&#xff0c;最近工作上处理的问题&#xff0c;把解决方案简单逻列出来&#xff0c;供有需要的朋友参考之 解决方案&#xff1a; 1、配置权限 <uses-permission android:name"android.permission.READ_MEDIA_IMAGES" /><uses-permission android:name&q…

(自用)learnOpenGL学习总结-高级OpenGL-立方体贴图

ok终于来到了立方体贴图了&#xff0c;在这里面我们可以加入好看的天空包围盒&#xff0c;这样的画我们的背景就不再是黑色的了&#xff01; 首先&#xff0c;立方体贴图和前面的sampler2D贴图一样&#xff0c;不过是6个2D组成的立方体而已。 那么为什么要把6个组合在一起呢&…

树莓派部署Nginx服务结合内网穿透实现远程访问本地站点

文章目录 1. Nginx安装2. 安装cpolar3.配置域名访问Nginx4. 固定域名访问5. 配置静态站点 安装 Nginx&#xff08;发音为“engine-x”&#xff09;可以将您的树莓派变成一个强大的 Web 服务器&#xff0c;可以用于托管网站或 Web 应用程序。相比其他 Web 服务器&#xff0c;Ngi…

怎样用流程自定义表单提升办公效率?

如果想要提升办公协作效率&#xff0c;可以试试低代码技术平台及流程自定义表单工具。不可否认的是&#xff0c;随着社会的进步和发展&#xff0c;传统的表单制作工具已经没有办法再满足业务量不断上涨的办公需求了&#xff0c;但是&#xff0c;借助专业的流程自定义表单工具就…

AES 加解密python实现

1. 要求 编程实现AES-128的加解密算法&#xff0c;满足给定明文和密钥加密得到密文&#xff0c;给定密文和密钥解密得到明文&#xff0c;最终用界面化的形式呈现。 2. 算法流程 程序主要分为加密与解密两个大模块。在加密模块中包括四个小模块&#xff0c;分别为轮密钥加、字…

Android 系统启动流程

依旧是带着问题再去学习 首先&#xff0c;Android是怎么启动的&#xff1f; Android服务是怎么启动的&#xff1f; Android线程是怎么切换的&#xff1f; Android ApplicationThread是怎么创建的&#xff1f; 那么接下来开始分析Android的启动流程 还是一步一图 先画一张流…

vp9协议梳理-header头文件

vp9协议梳理-header头文件 本文是对vp9视频码流中header中包含的语法元素的一个分类整理&#xff0c;及其对具体的解码过程的影响的分析。 这里写目录标题 vp9协议梳理-header头文件1. Vp9码流中的header头文件2. profile3. show_existing_frame, frame_to_show_map_idx4. fr…

What is Rust? Why Rust?

why Rust&#xff1f; 目前&#xff0c;Rust 变得越来越流行。然而&#xff0c;仍然有很多人&#xff08;和公司&#xff01;&#xff09;误解了 Rust 的主张价值是什么&#xff0c;甚至误解了它是什么。在本文中&#xff0c;我们将讨论 Rust 是什么以及为什么它是一种可以增强…

vivado 配置内存IP

配置内存IP UltraScale体系结构内存IP支持DDR3和DDR4 SDRAM的配置&#xff0c;QDRIIPLUS SRAM和RLDRAM3型接口。截至2015.3&#xff0c;内存IP已被拆分基于内存接口标准和工具流&#xff0c;将其划分为不同的IP。“自定义IP”对话框框包含基本和高级配置选项&#xff0c;其中包…

【C/C++ 05】快速排序

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序算法&#xff0c;其基本思想是&#xff1a;任取待排序序列中的某元素作为基准值&#xff0c;按照该基准值将待排序集合分割成两个子序列&#xff0c;左子序列中所有元素均小于基准值&#xff0c;右子序列中所有元素均大于…

数据在网络传输中为什么要加密?

在信息化浪潮席卷全球的今天&#xff0c;数据如同流淌在信息高速公路的生命血液&#xff0c;其安全传输的重要性不言而喻。随着网络空间中各种威胁与挑战日益凸显&#xff0c;加密技术已成为保护数据安全、维护用户隐私、确保业务连续性的关键手段。它就如同一道无形的防护盾&a…

Nestjs 全局拦截器

一、拦截器 拦截器作用&#xff1a; 在函数执行之前、之后绑定额外的逻辑转换函数的返回结果转换从函数抛出的异常扩展基本函数的行为根据所选条件重写函数 期望接口返回一个标准的json格式&#xff0c;利用拦截器对数据做全局的格式化 {code: "200",data: [],mess…

【文本到上下文 #7】探索 NLP 中的 Seq2Seq、编码器-解码器和注意力机制

一、说明 今天&#xff0c;我们将探讨序列到序列 &#xff08;seq2seq&#xff09; 模型的复杂工作原理&#xff0c;特别关注编码器-解码器架构和注意力机制。这些概念是各种 NLP 应用的基础&#xff0c;从机器翻译到问答系统。 这是可以期待的&#xff1a; Seq2Seq模型中的编码…