丰富图文详解B-树原理,从此面试再也不慌

本文始发于个人公众号:TechFlow,原创不易,求个关注


本篇原计划在上周五发布,由于太过硬核所以才拖到了这周五。我相信大家应该能从标题当中体会到这个硬核。

周五的专题是大数据和分布式,我最初的打算是和大家分享一下LSM树在分布式存储引擎当中的应用。但是想要能够真正深入理解了LSM的精髓,以及它构思巧妙的点,必须要对传统的数据库的B树和B+树有所了解。所以才有了今天的文章。

虽然我自己完整地将B树写了一遍,但是我并不建议初学者这么干,强行啃太难的数据结构除了容易劝退之外基本上没有太大的帮助。所以,虽然我起了这么一个标题,但是我并不会在文章当中贴太多的代码。而且即使是面试FLAG,只要不作死在简历里写自己是ACMer,一般也不会碰到让手写各种树的面试题。因此,相比于亲自实现,我们能够理解原理更加重要。

即使你是初学者,对于数据结构了解不多,也请不要退出,我有信心让你能够理解清楚B树的运行原理。


二叉与二叉搜索树


在详解原理之前,我们先复习一下简单的概念。

首先来看二叉树的概念,二叉树的概念本身很简单,除了根节点之外,每个节点最多有两个孩子。

比如这样一棵树就是一颗二叉树:

二叉树本身并没有太多用处,只是一个树形的数据结构而已,直到后来有大神想到了一个trick。如果我规定一颗二叉树上的元素拥有顺序,所有比它小的元素在它的左子树,比它大的元素在它的右子树,那么我们不就可以很快地查找某个元素了吗?

不得不说这是一个非常天才的想法,于是,二叉搜索树诞生了。

上图就是一个经典的二叉搜索树,比如我们要查找元素4,首先和根节点8进行比较。显然4 < 8,那么迭代到8的左子树3,4 > 3,于是往3的右子树走,走到6。4 小于6,于是走到了6的左子树,也就是4,我们找到了元素,结束。

在理想情况下,二叉树每多一层,可以存储的元素都增加一倍。也就是说n个元素的二叉搜索树,对应的树高为 log ⁡ ( n ) \log(n) log(n)。所以我们查找元素、插入元素的时间也为 log ⁡ ( n ) \log(n) log(n)

不过这是理想情况,显然在实际使用当中很有可能情况并不那么理想。举个简单的例子,如果插入的数据按照递增或者递减的顺序出现,那么所有的元素会线性排列,树形结构会退化成链表。显然在这种情况下,查找和插入的效率会蜕化成 O ( n ) O(n) O(n)。在算法领域可以接受一个数据结构不完美或者是绝大多数情况下可靠,但是不能接受可靠性未知。

为了解决二叉搜索树不平衡的问题,在此基础上提出了各种平衡树。比如数据结构课本上的AVL就是一颗经典的平衡树,平衡树的思路很朴素,就是在插入元素的时候进行判断,如果当前的元素的插入或删除会影响树的平衡性,那么则进行旋转操作,从而维持树的平衡。

正是因为引入了旋转的机制,才保证了二叉搜索树的性能,也因此大大提升了这个原本很简单的数据结构的难度。

上图就是一个经典的旋转操作,在增删改查操作当中,经常要用到旋转操作平衡整棵树,也因此对于程序员的逻辑和空间思维要求比较高。对初学者容易劝退。这里我们不深究旋转的细节,在B树当中不会用到旋转,我们只需要知道它是用来调整树的结构来重新构成平衡的就行了。


二叉和多叉


二叉搜索树理解了,多叉搜索树也就顺理成章了,根本原理是一样的,唯一的不同是多叉搜索树允许节点中的元素数量超过1。也就是一个节点可以存储多个元素,并且会有多个子树分支。

在B树当中有一个非常巧妙的设计,就是每一个节点的孩子个数是元素的数量+1。并且和二叉搜索树一样,存在大小顺序的关联。

如图,根节点有两个元素3和9,并且有3个孩子节点,刚好对应了3个区间。分别是小于3的,在3和9中间的以及大于9的,那么根据我们要查找的元素的大小,我们很容易判断究竟应该选择哪一个分支。而且节点中的元素是有序的,我们可以使用二分查找进行高效搜索。

我们来思考一个问题,既然二叉搜索树也可以完成节点的高效增删改查,我们为什么又需要搞出这个多叉搜索树呢?和二叉搜索树相比,它究竟有什么得天独厚的优点呢?

我们光看是看不出来的,需要了解一下B树实际的应用场景。B树主要用在各大存储文件系统和数据库系统当中。在这些场景下数据总量很大,我们不可能将它们都存储在内存当中。所以为了解决这个问题,我们会在树节点当中存储孩子节点的在磁盘上的地址。在需要访问的时候通过磁盘加载将孩子节点的信息读取到内存当中。也就是说在数据库当中我们遍历树的时候也伴随着磁盘读取。

我们之前介绍MapReduce的时候曾经说过

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值