查找树(AVL、B、B+、红黑树)

一、二叉查找树(BST)

1.1 定义

二叉查找树或者是一棵空树,或者是具有下列性质的二叉树:

  • 若他的左子树不为空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别是二叉搜索树。

二叉查找树的查找时间复杂度最优为 O(logN),添加结点的时间复杂度为 O(1),删除结点的时间复杂度最优为 O(logN),查找快于链表,添加和删除快于数组。

在这里插入图片描述

1.2 插入

​ BST 的插入操作非常简单,只需要找到插入的位置改变一下索引即可。

1.3 删除

​ 删除操作依据结点可分为三种情况:

  1. 叶子结点:直接删除,比如删除 37。直接删了就可以;
  2. 仅有左或右子树的结点:使用仅有的孩子来代替删除的结点。如,删除 35,把 47 的指针指向 37。
  3. 左右子树都有的结点:使用该结点的前驱(左子树的最大值)或者后继(右子树的最小值)来代替。如,删除 62,用 58 或者 73 来代替根结点。

1.4 存在的问题

​ 二叉查找树的形状是不确定的,所以很有可能是一棵斜树,那么查找的时间复杂度又变回了 O(n)

二、AVL 树(平衡二叉树)

2.1 定义

​ AVL 树是一种二叉排序树,其中每一个结点的左子树和右子树的高度差至多等于 1。

2.2 插入

​ 插入结点可能导致树不平衡,所以要进行调整,分为以下四类情况:

外部:(需要一次旋转)

  1. 插入的结点是左子树的左孩子(LL)

  2. 插入的结点是右子树的有孩子(LR)

内部:(需要两次旋转)

  1. 插入的结点是左子树的右孩子(LR)

  2. 插入的结点是右子树的左孩子(RL)

    LL:做一次右旋,改变一下右孩子的父结点

在这里插入图片描述
例:

在这里插入图片描述

RR:做一次左旋,改变一下左孩子的父亲

在这里插入图片描述

LR:先做左旋,再做右旋

在这里插入图片描述

例:

在这里插入图片描述

RL:先做右旋,再做左旋

在这里插入图片描述

2.3 删除

​ AVL 的删除操作与普通 BST 的删除操作一样,也需要考虑三种情况:

  1. 叶子结点:直接删除;

  2. 仅有左或右子树的结点:使用仅有的孩子来代替删除的结点;

  3. 左右子树都有的结点:使用该结点的前驱(左子树的最大值)或者后继(右子树的最小值)来代替。

    删除后可能导致树不平衡,所以需要按照插入里讲到的旋转来使树重新平衡。

2.4 存在的问题

​ AVL 树的查找性能非常好,但是在插入和删除的时候,为了保持严格的整体平衡,可能会有多次旋转,导致性能下降,所以引入了追求局部而不是非常严格整体平衡的红黑树

三、红黑树

3.1 定义

​ 红黑树是一种二叉查找树,但在每一个结点增加了一个存储位表示结点的颜色,可以是红色或黑色。通过对任意一条从根到叶子的路径上各个结点着色的方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因此红黑树是一种弱平衡二叉树,相对于严格的 AVL 树来说,它的旋转次数少,所以,对于插入、删除性能要求高的时候使用红黑树,对于查找性能要求高的时候使用 AVL 树。

​ 对于插入操作,红黑树和 AVL 树都最多需要两次旋转就可以平衡;

​ 对于删除操作,AVL 树需要从当前结点一直到树根维持平衡,时间复杂度为 O(logN),而红黑树最多只需要 3 次旋转就能平衡,时间复杂度为 O(1)

3.2 性质

  1. 每个结点或者是红色,或者是黑色;
  2. 根是黑色的;
  3. 如果一个结点是红色的,那么它的子结点必须是黑色的;
  4. 从一个结点到一个 null 引用的每一条路径必须包含相同数目的黑色结点。

四、B 树

​ 上面所描述的树都是可以把数据全部存储在内存中进行查找的,但是如果数据太大导致内存中放不下,那么就必须存储到磁盘中,为了减少访问磁盘的次数,就需要新的数据结构。

​ 之前所描述的树,有一个共同的特点就是每个结点只能存储一个元素,这会导致树的高度非常大,增加访问磁盘的次数,所以为了减少树的高度,必须使用多路查找树,B 树是多路查找树的一种。

4.1 定义

​ B 树是一种多路查找树,结点最大的孩子数目 m 称为 B 树的阶。一个 m 阶的 B 树具有如下属性:

注:m 一般是奇数,这样在分裂的时候才能正好找到中间结点

  1. 如果根结点不是叶结点,则其至少有两棵子树;

  2. 每一个非根的分支结点都有 k - 1 个元素和 k 个孩子,其中 [m / 2] ≤ k ≤ m。[] 代表向上取整

  3. 所有的叶子结点都位于同一层次;

  4. 所有的分支结点包含下列信息数据(n,A0,K1,A1,K2,A2,···,KnAn),其中:Ki 为关键字,且 Ki < Ki+1;Ai为指向子树根结点的指针,且 Ai-1 所指子树中所有结点的关键字均小于 Ki,An 所指子树中所有结点的关键字均大于 Kn

在这里插入图片描述

4.2 插入

  1. 把结点插入到叶结点;

  2. 如果叶结点的数量大于 m - 1,则把该叶结点分裂:把中间的结点提升为父结点;

  3. 如果父结点的数量大于 m - 1,继续提升,以此循环,循环的最大次数就是把根分裂;

    例:把下列数字构造成一棵 5 阶 B 树1, 12, 8, 2,25, 5, 14, 28, 17, 7, 52, 16, 48, 68, 3, 26, 29, 53, 55, 45 (图片是重点)

在这里插入图片描述

4.3 删除

​ B 树的删除分为两大种情况,分别是删除叶子中的关键字和删除内部结点中的关键字,在删除完后为了保持 B 树的结构,又又两种情况。

  1. 删除的是叶子结点中的关键字,如果把该关键字删除,没有导致该结点中的数据少于 m - 1,就可以直接删除;

在这里插入图片描述

  1. 删除的是内部结点中的关键字,使用该结点的前驱(左孩子的最大值)或者后继(右孩子的最小值)来顶上;

    在这里插入图片描述

如果 1 和 2 导致叶子结点中的关键字少于 m - 1,需要借助叶子结点的兄弟结点来恢复

  1. 如果兄弟结点的关键字个数足够多,就用兄弟结点的关键字来替代被删除结点的关键字;

    例:

在这里插入图片描述

  1. 如果兄弟结点的关键字不够,则把自己和兄弟结点合并。

    例:

在这里插入图片描述

4.4 优点

​ 在一个典型的 B 树应用中,要处理的硬盘数据量很大,因此无法一次全部装入内 存。因此我们会对 B 树进行调整,使得 树的阶数(或结点的元素)与硬盘存储的页面(211~214字节)大小相匹配。比如一棵 B 树的阶为 1001,高度为 2,它可以存储超过 10 亿个关键字,我们只需要让根结点保存在内存中,那么这棵树上,寻找某一个关键字最多需要 2 次读取硬盘

在这里插入图片描述

4.5 缺点

​ 在 B 树的结构中,我们往返于每个结点意味着必须在硬盘的页面之间多次访问,如图,我们希望中序遍历所有元素,遍历顺序就是:页面2 -> 页面1 -> 页面3 -> 页面1 -> 页面4 -> 页面5。因为这里的页是加载到磁盘中的,所以每次遍历结点时,都要把页加载到磁盘,然后把之前遍历过的元素再扫描一遍。

在这里插入图片描述

​ 为了解决 B 树的问题,我们引入了新的数据结构——B+ 树

五、B+ 树

5.1 定义

​ B+ 树是应文件系统所需而出的一种 B 树的变形树,在 B+ 树中,出现在分支结点的元素会被当作它们在该分支结点位置的中序后继者(叶子结点)中再次列出。另外,每一个叶子结点都会保存一个指向后一叶子结点的指针。

​ B+ 树和 B 树有如下差别

  • 有 n 棵子树的结点中包含有 n 个关键字(B 树有 n - 1 个)
  • 所有的叶子结点包含全部的关键字信息,及指向这些关键字记录的指针
  • 所有分支结点可以看成是索引,结点中仅含有其子树中的最大(或最小)关键字。

5.2 B+ 树为什么更适合数据库索引

  1. B+ 树所有的叶子结点都形成了链表,更便于范围查询
  2. B+ 树所有的数据都在叶子结点上存储,查找效率更加稳定
  3. B+ 树的中间结点不存数据只存索引,所以中间结点可以存储更多的元素,可以减小树的高度,从而减少 IO 次数
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值