【数据结构】二叉树 平衡二叉树 B树 B+树

1. 背景

B+ 树在数据库中是最常见的索引结构,在MYSQL 中聚簇索引和非聚簇 辅助索引 用的都是 B+ 树的结构。

在聊 B+ 树之前先聊一下B+ 树是怎么来的,解决了什么问题,才能更好的了解为什么我们需要 B+ 树。

2. 二分查找

二分也称为折半查找,如果我们获得了一组有序的数据集合,比如 1,3,4,5,7,10. 如果想在集合中找到数字为7的值,如果是顺序查找的话平均查找次数是 (1+2+3+4+5+6) / 6 = 3.5,如果使用折半查找的话,则是 (3+2+3+1+2+3) /6 = 2.3. 如果算时间复杂度的话,顺序查找的时间复杂度是 O(n),折半查找的时间复杂度是 O(logn) .

3. 二叉树

以上面的例子为例(1,3,4,5,7,10),二叉树是如下的结构,符合我们前面说的时间复杂度和查找次数。

在二叉树的定义中,每个节点的左侧节点小于当前节点的数据,右侧节点大于当前节点的数据,每个节点最多有2个叶子节点。

二叉树的问题,二叉树因为没有规定树深度的最小差额,所以可能会得到如下的二叉树,这个二叉树的平均查询查找次数为 (1+2+3+4+5+5) /6 = 3.3 , 这已经和顺序查找 3.5 很接近了。如果二叉树是只有一边的话,那就和顺序表的查询效率一样了,所以树的查询效率很大一部分就是在减少树的高度。

mysql 使用 B+树 也是因为减少树的高度,每减少一次树的高度在 mysql 的视角就减少了一次 IO。

4. 平衡二叉树

因为二叉树有上面提到的问题,所以才引入了平衡二叉树,也称为 AVL 树(Adelson-Velsky and Landis)。

平衡二叉树定义了,每个节点的深度不能相差大于1,如果大于 1的话,AVL 树会自己通过左旋和右旋进行自平衡。

4.1. 左旋 右旋

左旋和右旋的思路其实是一样的,围绕着 7 或者 4 这个点,进行左旋和右旋之后,可以互转。

从理解上只需要理解转变2个指针即可。

右旋:

  1. 自己变为左子树的右子树(7变成4的右子树)
  2. 左子树的右子树变成自己的左子树(5变成7的左子树)

左旋:

  1. 自己变为右子树的左子树(4变成7的左子树)
  2. 右子树的左子树变成自己的右子树(5变成4的右子树)

java 代码如下:

/** * (x) (y) * / \ / * (x1) (y) --> (x) * / / \ * (T2) (x1) (T2) * * 左旋操作 */ private Node leftRotate(Node x) { Node y = x.right; Node T2 = y.left; // Perform rotation y.left = x; // x 的右子树 x.right = T2; // Return new root return y; } /** * (y) (x) * / \ / \ * (x) (y1) --> (x1) (y) * / \ / \ * (x1) (T2) (T2) (y1) * 右旋 * @param y * @return */ private Node rightRotate(Node y) { Node x = y.left; Node T2 = x.right; // Perform rotation x.right = y; y.left = T2; // Return new root return x; }

通过程序来构建上面图例中的树,进行左旋后再进行候选,会获得如下结果。

before reBalance 4 / \ / \ 3 7 / \ 5 10 after leftRotate 7 / \ / \ 4 10 / \ 3 5 after rightRotate 4 / \ / \ 3 7 / \ 5 10

5. B树

B树,B树的B是 balance 的意思,所以B树是平衡树,和平衡二叉树的最大的区别就是B树是一颗多叉树。

为什么需要 B树,其原因是还是为了性能考虑,上文有提到树的查询效率取决于树的深度,深度越深的树,查询效率越慢,深度越是浅,查询则效率越是高,那减少深度的一大方法就是把二叉树变成多叉树。

如果数据库的索引以 B+ 树来构造,我们会得到如下的一棵树。

每个节点包含如下几个数据:

  1. 索引关键值,用于寻址
  2. 子节点的磁盘指针,用于定位下个子节点的磁盘位置,如图中 P1 P2
  3. 数据,索引对应的真实数据

B树的特点:

  1. 因为是平衡多叉树,所以每个节点保存的数据相对于平衡二叉树来说增多了
  2. 每个节点除了保存索引值,还保存实际的数据

6.B+ 树

B+树可以说是 B树的升级版,在B树的基础上更进一步的提高了树的稳定性、提升查询性能。

以上面的图可以知道,如果想提高性能,需要减少的树的高度,因为树的每多一个深度就意味着查询多一次 IO,B+ 树优化的核心思路:

  1. 每一个磁盘块上,尽量保存多的节点,通过这个来减少树的深度。
  2. 叶子节点和叶子节点之间,通过链表串联起来,以提升范围查询的效率。

B+ 树和 B树的区别:

  1. 所有的索引值都在叶子节点,非叶子节点只保存关键的数据,以增加磁盘块存储关键信息的量,从而减少树的高度,减少查询时候 IO 的次数。

  2. 所有的索引值都在叶子节点,而B树因为在非叶子节点会保存数据,部分索引子如果在非叶子节点存在的话,在叶子节点不会出现,比如上面 B树的 10, 20, 50 等节点,B+树把所有索引都保存在了叶子节点,有2个好处

  3. 查询效率稳定,几乎等于 O(logn)

  4. 容易范围查找,在范围查找的时候,查找自己的兄弟节点,不需要往上追溯查询父节点。

  5. 叶子节点通过链表关联,方便范围查找。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
B树是一种常用的索引数据结构,是从二叉查找树、平衡二叉树演化而来的。它被广泛应用于数据库系统中,包括MySQL中的InnoDB存储引擎。B树的特点是具有多个子节点,可以在每个节点中存储多个键值对,而不仅仅是一个键和一个值。通过使用B树索引,数据库可以更高效地存储和查找数据。 B树索引在InnoDB中的实现方式是,将每个节点作为一个数据页。从数据页的角度来看,B树查询过程是按照一定的规则进行的。查询过程从根节点开始,根据键的值进行比较,决定向左子节点还是向右子节点继续搜索。在每个节点中,根据节点存储的键值对进行比较,直到找到匹配的键值对或者确定无法找到匹配的键值对为止。 B树的优点在于可以提供较快的查询性能,因为B树具有平衡性,所以它的高度相对较低,每次查询只需经过几个节点即可找到目标数据。此外,B树还支持高效的插入和删除操作,因为它的平衡性可以保持树的结构相对稳定。 总之,B树是一种常用的索引数据结构,通过使用多个子节点和在节点中存储多个键值对的方式,可以提供高效的数据存储和查询性能。它在数据库系统中得到广泛应用,包括MySQL的InnoDB存储引擎。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [MySQL索引-B+树(讲得通透)](https://blog.csdn.net/zsz0147/article/details/117985568)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [MYSQL索引数据结构----B+树](https://blog.csdn.net/sanylove/article/details/127245540)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值