B树和B+树详解
一 B树
1.B树的定义:B树(B-tree)是一种树状数据结构,它能够存储数据、对其进行排序并允许以O(log n)的时间复杂度运行进行查找、顺序读取、插入和删除的数据结构。B树,概括来说是一个节点可以拥有多于2个子节点的二叉查找树。
2.B树的特征:
- 根节点至少有两个子节点
- 每个中间节点都包含k-1个元素和k个孩子,其中 m/2 ≤ k ≤ m (m为树的阶)
- 每个叶子节点都包含k-1个元素,其中 m/2 ≤ k ≤ m (m为树的阶)
- 每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域划分(一个结点有k个孩子时,必有k-1个元素才能将子树中所有元素划分为k个子集)
3.B树的操作
3.1 B树的查找:如下图,查询元素8

第一次磁盘IO:把15所在节点读到内存中,然后与8做比较,小于15,找到下一个节点(5和9对应的节点)
第二次磁盘IO:把5和9所在的节点读到内存中,然后与8做比较,5<8<9,找到下一个节点(6和8对应的节点)
第三次磁盘IO:把6和8所在节点读到内存中,然后与8做比较,找到了元素8
3.1 B树的插入: 将元素7插入下图中的B树

步骤一:自顶向下查找元素7应该在的位置,即在6和8之间
步骤二:三阶B树中的节点最多有两个元素,把6 7 8里面的中间元素上移(中间元素上移是插入操作的关键)
步骤三:上移之后,上一层节点元素也超载了,5 7 9中间元素上移,现在根节点变为了 7 15
步骤四:要对B树进行调整,使其满足B树的特性,最终如下图:

二 B+树
B+树是B树的一种变形体,它与B树的差异在于:
- 有K个子节点的节点必然有K个关键码
- 非叶节点仅具有索引作用,元素信息均存放在叶节点中
- 树的所有叶节点构成一个有序链表,可以按照关键码排序的次序遍历全部记录
B+树的优势:
- 由于B+树在内部节点上不包含数据信息,因此在内存页中能够存放更多的key。 数据存放的更加紧密,具有更好的空间局部性。因此访问叶子节点上关联的数据也具有更好的缓存命中率。
- B+树的叶子节点都是相连的,因此对整棵树的遍历只需要一次线性遍历叶子节点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。

总结:我们知道二叉查找树的时间复杂度是O(logN),效率已经足够高。为什么出现B树和B+树呢?当大量数据存储在磁盘上,进行查询操作时,需要先将数据加载到内存中(磁盘IO操作),而数据并不能一次性全部加载到内存中,只能逐一加载每个磁盘页(对应树的一个节点),并且磁盘IO操作很慢,平衡二叉树由于树深度过大而造成磁盘IO读写过于频繁,进而导致效率低下。为了减少磁盘IO的次数,就需要降低树的深度,那么就引出了B树和B+树:每个节点存储多个元素,采用多叉树结构。这样就提高了效率,比如数据库索引,就是存储在磁盘上,采用的就是B+树的数据结构。
B树和B+树详解的更多相关文章
- 哈夫曼树(三)之 Java详解
前面分别通过C和C++实现了哈夫曼树,本章给出哈夫曼树的java版本. 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载请注明出处:htt ...
- 哈夫曼树(二)之 C++详解
上一章介绍了哈夫曼树的基本概念,并通过C语言实现了哈夫曼树.本章是哈夫曼树的C++实现. 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载 ...
- B树、B+树、B*树三者的对比详解
转载至:https://www.2cto.com/database/201805/745822.html 对比 B+树是B树的变体,B*树又是B+树的变体,是一脉相承法治国拉的,不断解决新一阶段的问题 ...
- AVL树的旋转操作详解
[0]README 0.0) 本文部分idea 转自:http://blog.csdn.net/collonn/article/details/20128205 0.1) 本文仅针对性地分析AVL树的 ...
- 有趣的 zkw 线段树(超全详解)
zkw segment-tree 真是太棒了(真的重口味)!写篇博客纪念入门 emmm...首先我们来介绍一下 zkw 线段树这个东西(俗称 "重口味" ,与 KMP 类似,咳咳. ...
- BZOJ 1912: [Apio2010]patrol 巡逻 (树的直径)(详解)
题目: https://www.lydsy.com/JudgeOnline/problem.php?id=1912 题解: 首先,显然当不加边的时候,遍历一棵树每条边都要经过两次.那么现在考虑k==1 ...
- 可持久化线段树(主席树)(图文并茂详解)【poj2104】【区间第k大】
[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=63740442 向大(hei)佬(e)实力学(di ...
- AVL树(二叉平衡树)详解与实现
AVL树概念 前面学习二叉查找树和二叉树的各种遍历,但是其查找效率不稳定(斜树),而二叉平衡树的用途更多.查找相比稳定很多.(欢迎关注数据结构专栏) AVL树是带有平衡条件的二叉查找树.这个平衡条件必 ...
- 决策树--CART树详解
1.CART简介 CART是一棵二叉树,每一次分裂会产生两个子节点.CART树分为分类树和回归树. 分类树主要针对目标标量为分类变量,比如预测一个动物是否是哺乳动物. 回归树针对目标变量为连续值的情况 ...
- 从Trie树(字典树)谈到后缀树
转:http://blog.csdn.net/v_july_v/article/details/6897097 引言 常关注本blog的读者朋友想必看过此篇文章:从B树.B+树.B*树谈到R 树,这次 ...
随机推荐
- 架构师入门:Spring Cloud系列,Hystrix与Eureka的整合
和Ribbon等组件一样,在项目中,Hystrix一般不会单独出现,而是会和Eureka等组件配套出现.在Hystrix和Eureka整合后的框架里,一般会用到Hystrix的断路器以及合并请求等特性 ...
- springboot项目容器化
创建一个简单的springboot项目,依赖中加入: 编写一个Restfull接口: 编写启动类: 启动项目,浏览器访问该接口,得到想要的结果.下面,就将这个项目进行Docker容器化(applica ...
- RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2版本正式发布
RDIFramework.NET .NET快速信息化系统开发框架 V3.2版本 正式发布 精益求精求完美! 1.RDIFramework.NET框架介绍 RDIFramework.NET,基于.NE ...
- Java内存模型JMM 高并发原子性可见性有序性简介 多线程中篇(十)
JVM运行时内存结构回顾 在JVM相关的介绍中,有说到JAVA运行时的内存结构,简单回顾下 整体结构如下图所示,大致分为五大块 而对于方法区中的数据,是属于所有线程共享的数据结构 而对于虚拟机栈中数据 ...
- AspNetCore 基于AOP实现Polly的使用
前言 说起AOP,其实我们在做MVC/API 的时候应该没少接触,比如说各种的Fitter 就是典型的AOP了. 本来在使用Polly的时候我最初的打算是使用过滤器来实现的,后来发现实现起来相当的 ...
- 折腾Java设计模式之迭代器模式
迭代器模式 Provide a way to access the elements of an aggregate object sequentially without exposing its ...
- Vue.js实现登录功能
编写html,通过vue-resource.js库向后台提交数据 <!DOCTYPE html> <html lang="en"> <head> ...
- Math.floor(Math.random()*3+1)
Math.random():获取0~1随机数 Math.floor() method rounds a number DOWNWARDS to the nearest integer, and ret ...
- 章节十、8-XPath---如何构建有效的XPath
以下演示操作以该网址中的内容为例:https://learn.letskodeit.com/?_ga=2.143454972.85111248.1555037144-697706367.1554889 ...
- Vue.js02:数据绑定v-model用法
<!-- v-model 实现数据的双向绑定 --> <!-- v-model 只能用在表单元素中 --> 示例: <!DOCTYPE html> <!-- ...