一、B 树是一种多叉平衡查找树

相较于二叉结构的红黑树,B 树是多叉结构,所以在元素数量非常多的情况下,B 树的高度不会像二叉树那么大,从而保证查询效率。

一棵含 n 个结点的 B 树的高度 h = O(logtn),其中 t 是 B 树的最小度数。

  • 提出多叉平衡查找树的思维历程:查询效率要更高 ----> 查询次数要更少 ----> 查找树的高度要更低 ----> 每个结点保存的信息要更多 ----> 多叉

下图是一棵B树的示意图:

二、B 树的定义

《算法导论》中用最小度数 t 来定义 B 树,所谓最小度数,即结点拥有的最小孩子数。

一棵最小度数为 t 的 B 树是满足如下四个条件:

  1. 每个非根结点至少含有 t - 1 个关键字,根结点至少含有 1 个关键字
  2. 每个结点至多含有 2t - 1 个关键字,即一个结点至多可有 2t 个孩子(如果一个结点恰好有 2t - 1 个关键字,我们就说这个结点是满的)
  3. 一个结点 u 中的关键字按非降序排列,如u.key≤ u.key≤ … ≤ u.keyn-1
  4. 每个节点的关键字对其子树的范围分割,设节点 u 有 n + 1 个指针,指向其 n + 1 棵子树,指针为u.p0, u.p1, u.p2, …, u.pn,关键字 ki 为 u.pi 所指的子树中的关键字,有 k≤ u.key0 ≤ k1 ≤ u.key ≤ u.keyn-1 ≤ kn 成立
  5. 所有叶子结点具有相同的深度,即树的高度 h(这表明了 B 树是平衡的)
/* B树结点结构 */
struct BTreeNode {
int keyNum; // 关键字的数目
BTreeNode *parent; // 指向父结点
BTreeNode **ptr; // 子树指针向量:ptr[0]...ptr[keyNum]
KeyType *key; // 关键字向量;key[0]...key[keyNum-1]
};

三、查询操作

例题:一棵已经建立好的B树如下图所示,要求查找关键字为29的文件。

  • 结点中的关键字表示磁盘文件的文件名,而小红块表示对应的关键字所代表的文件在硬盘中的存储位置,P是指针
  • 指针、关键字以及关键字所代表的文件地址合起来构成了B树的一个结点,这个结点存储在一个磁盘块上

  • 假如每个磁盘块正好可以存放一个B树的结点(正好存放2个文件名)。那么一个B树结点就代表一个盘块,而子树指针就是存放另外一个盘块的地址

搜索过程如下:

  1. 从根结点开始,读取根结点信息,根结点有2个关键字:17和35。因为17 < 29 < 35,所以找到指针P2指向的子树,也就是磁盘块3(1次I/0操作)

  2. 读取当前结点信息,当前结点有2个关键字:26和30。因为26 < 29 < 30,所以找到指针P2指向的子树,也就是磁盘块8(2次I/0操作)

  3. 读取当前结点信息,当前结点有2个关键字:28和29。找到了!(3次I/0操作)

由上面的过程可见,同样的操作,如果使用平衡二叉树,那么需要至少4次 I/O 操作,而且这种优势还会随着结点数的增加而更加明显。另外,因为 B 树结点中的关键字都是排好序的,所以,在结点中的信息被读入内存之后,可以采用二分查找这种快速的查找方式,更进一步减少了读入内存之后的计算时间。由此可见,对于外存数据结构来说,I/O操作的次数是其查找信息中最大的时间消耗,而我们要做的所有努力就是尽量在搜索过程中减少I/O操作的次数。

如何理解“树的高度过大而造成磁盘I/O读写过于频繁,进而导致查询效率低下”这句话?

在大规模数据存储方面,大量数据存储在外存磁盘中,而在外存磁盘中读取/写入块(block)中某数据时,首先需要定位到磁盘中的某磁盘块。

磁盘读取数据是以盘块(block)为基本单位的。位于同一盘块中的所有数据都能被一次性全部读取出来。而磁盘I/O代价主要花费在盘块查找时间T上。因此我们应该尽量将相关信息存放在同一盘块,同一磁道中。或者至少放在同一柱面或相邻柱面上,以求在读/写信息时尽量减少磁头来回移动的次数,避免过多的查找时间T。

因此,使用B树使得树的高度更低,从而需要查找的盘块也就更少(即减少磁盘I/O操作的次数),所需的盘块查找时间也就越低,查询效率自然提高。

四、插入/删除操作

参考博客:B树&B+树B树与B+树

6. B树的更多相关文章

  1. B树——算法导论(25)

    B树 1. 简介 在之前我们学习了红黑树,今天再学习一种树--B树.它与红黑树有许多类似的地方,比如都是平衡搜索树,但它们在功能和结构上却有较大的差别. 从功能上看,B树是为磁盘或其他存储设备设计的, ...

  2. ASP.NET Aries 入门开发教程8:树型列表及自定义右键菜单

    前言: 前面几篇重点都在讲普通列表的相关操作. 本篇主要讲树型列表的操作. 框架在设计时,已经把树型列表和普通列表全面统一了操作,用法几乎是一致的. 下面介绍一些差距化的内容: 1:树型列表绑定: v ...

  3. 再讲IQueryable<T>,揭开表达式树的神秘面纱

    接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...

  4. HDU1671——前缀树的一点感触

    题目http://acm.hdu.edu.cn/showproblem.php?pid=1671 题目本身不难,一棵前缀树OK,但是前两次提交都没有成功. 第一次Memory Limit Exceed ...

  5. 算法与数据结构(十一) 平衡二叉树(AVL树)

    今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...

  6. [C#] C# 知识回顾 - 表达式树 Expression Trees

    C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...

  7. bzoj3207--Hash+主席树

    题目大意: 给定一个n个数的序列和m个询问(n,m<=100000)和k,每个询问包含k+2个数字:l,r,b[1],b[2]...b[k],要求输出b[1]~b[k]在[l,r]中是否出现. ...

  8. bzoj1901--树状数组套主席树

    树状数组套主席树模板题... 题目大意: 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[ ...

  9. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  10. jquery-treegrid树状表格的使用(.Net平台)

    上一篇介绍了DataTable,这一篇在DT的基础之上再使用jquery的一款插件:treegrid,官网地址:http://maxazan.github.io/jquery-treegrid/ 一. ...

随机推荐

  1. 常用 超全局数组$_server

    $_SERVER 是一个包含了诸如头信息(header).路径(path).以及脚本位置(script locations)等等信息的数组.这个数组中的项目由 Web 服务器创建.不能保证每个服务器都 ...

  2. com.alibaba.druid检测排查数据库连接数不释放定位代码

    1.可能标题说的很不明白,其实就是这样一个情况,一个工程项目错误日志出现GetConnectionTimeoutException: wait millis 90000, active 22000的异 ...

  3. day89 DjangoRsetFramework学习---restful规范,解析器组件,Postman等

     DjangoRsetFramework学习---restful规范,解析器组件,Postman等           本节目录 一 预备知识 二 restful规范 三 DRF的APIView和解析 ...

  4. 将Windows 7安装到移动固态硬盘(U盘)

    由于工作的原因,有时需要用两台电脑工作,而搞开发的人大多又是追求计算机性能的人,所以笔记本电脑自然不轻,更何况两台. 两台电脑折磨我半年多,终于下定决心将个系统安装到移动固态硬盘中,背一台无硬盘电脑加 ...

  5. 工作和面试中的gdb

    gdb是C/C++程序员必备的专业技能,工作中gdb最常用的场景有两个,一个是分析core文件,另一个是调试程序. 分析core文件的方法如下: 1.gdb 程序名 core文件名 2.bt或wher ...

  6. go基础语法-变量定义

    1.基础定义 变量类型在变量名后 var a int var s string 2.定义并赋值 var a,b int = 1,2 var s string="abc" 3.类型推 ...

  7. 【 C 】高级字符串查找之查找标记(token)函数 strtok介绍

    我的csdn博客 一个字符串常常包含几个单独的部分,它们彼此被分隔开来.每次为了处理这些部分,你首先必须把它们从字符串中抽取出来. 这个任务有#include<string.h>中的str ...

  8. 20155203 2016-2017-2 《Java程序设计》第10周学习总结

    20155203 2016-2017-2 <Java程序设计>第10周学习总结 教材学习内容总结 网络编程(Java Socket编程) Java最初是作为网络编程语言出现的,其对网络提供 ...

  9. 20155210 潘滢昊 Java第三次实验

    Java第三次实验 实验内容 在IDEA中使用工具(Code->Reformate Code)把代码重新格式化 在码云上把自己的学习搭档加入自己的项目中,确认搭档的项目加入自己后,下载搭档实验二 ...

  10. 20155318 《Java程序设计》实验一(Java开发环境的熟悉)实验报告

    20155318 <Java程序设计>实验一(Java开发环境的熟悉)实验报告 一.实验内容及步骤 (一)命令行下Java程序开发 步骤一(新建文件夹): 打开windows下的cmd → ...