面经手册 · 第5篇《看图说话,讲解2-3平衡树「红黑树的前身」》

做者:小傅哥
博客:https://bugstack.cnhtml

沉淀、分享、成长,让本身和他人都能有所收获!😄

1、前言

讲道理5年开发,没用过数据结构,你只是在作CRUD!程序员

不少时候大部分程序员👨‍💻‍头疼于,查询慢、效率低、一堆的关联SQL,主要缘由是在程序设计上没有作出很好的数据结构。固然也还有一部分是因为老业务代码,或者没有用到一些大数据服务等。面试

数据结构、算法、设计模式,是每个程序员成长过程当中的内功心法修炼,而你的新技能用的再绚、多线程使的再六、加锁玩的再牛🐂,也只能说明你这我的身体好,但身体好是不能抗住子弹的。只有身体+心法都好,都能纵横捭阖算法

这一章节是结合HashMap的延展,在Jdk1.8中HashMap是使用桶数组+链表和红黑树实现,因此顺着上一章节的核心原理和API功能讲解后,原本这一章节想直接进入到红黑树,但若是想把红黑树学明白,就须要了解他的前因后果,也就是它的前身2-3树🌲。数据库

2、面试题

谢飞机,考你几个简单的知识点🦀设计模式

  1. 飞机,看你简历写了解数据结构,能够简单介绍下2-3树吗?
  2. 这种树节点有什么特色,与你了解其余的树结构对比下?
  3. 你看这个图,向里面插入和删除节点,要怎么操做?

🤥飞机,回去等消息吧!数组

3、什么是2-3树

平常的学习和一部分伙伴的面试中,居然会听👂到的是;从HashMap中文红黑树、从数据库索引为B+Tree,但问2-3树的状况就不是不少了。数据结构

1. 为何使用树结构

从最根本的缘由来看,使用树结构就是为了提高总体的效率;插入、删除、查找(索引),尤为是索引操做。由于相比于链表,一个平衡树的索引时间复杂度是O(logn),而数组的索引时间复杂度是O(n)。多线程

从如下的图上能够对比,二者的索引耗时状况;函数

公众号:bugstack虫洞栈 & 链表与二叉搜索树(Binary Search Tree)时间复杂度对比

  • 从上图能够看到,使用树结构有效的下降时间复杂度,提高数据索引效率。
  • 另外这个标准的树结构,是二叉搜索树(Binary Search Tree)。除此以外树形结构还有;AVL树、红黑树、2-3树等

2. 二叉搜索树退化链表

在树的数据结构中,最早有点是二叉查找树,也就是英文缩写BST树。在使用数据插入的过程当中,理想状况下它是一个平衡的二叉树,但实际上可能会出现二叉树都一边倒,让二叉树像列表同样的数据结构。从而树形结构的时间复杂度也从O(logn)升级到O(n),以下图;

公众号:bugstack虫洞栈 & 二叉搜索树退化链表

  • 二叉搜索树的数据插入过程是,插入节点与当前树节点作比对,小于在左,大于在右。
  • 随着数据的插入顺序不一样,就会出现彻底不一样的数据结构。多是一棵平衡二叉树,也极有可能退化成链表的树。
  • 当树结构退化成链表之后,整个树索引的性能也跟着退化成链表。

综上呢,若是咱们但愿在插入数据后又保持树的特色,O(logn)的索引性能,那么就须要在插入时进行节点的调整

3. 2-3树解决平衡问题

2-3树是什么结构,它怎么解决平衡问题的。带着问题咱们继续🤔。

2-3树是一种很是巧妙的结构,在保持树结构的基础上,它容许在一个节点中能够有两个元素,等元素数量等于3个时候再进行调整。经过这种方式呢,来保证整个二叉搜索树的平衡性。

这样说可能尚未感受,来看下图;

公众号:bugstack虫洞栈 & 2-3树解决平稳问题

  • 左侧是二叉搜索树,右侧是2-3平衡树,分别插入节点四、5,观察树形结构变化。
  • 二叉搜索树开始出现偏移,节点一遍倒。
  • 2-3树经过一个节点中存放2到3个元素,来调整树形结构,保持平衡。所谓的保持平衡就是从根节点,到每个最底部的本身点,链路长度一致。

2-3树已经能够解决平衡问题那么,数据是怎么存放和调整的呢,接下来咱们开始分析。

4、2-3树使用

1. 树结构定义和特色性质

2-3树,读法;二三树,特性以下;

序号 描述 示意图
1 2-,1个数据节点2个树杈
2 3-,2个数据节点3个树杈
3 三叉与两叉的不一样点在于,除了两边的节点,中间件还有一个节点。这个节点是介于二、4之间的值。
4 当随着插入数据,会出现临时的一个节点中,有三个元素。这时会被调整成一个二叉树。

综上咱们能够总结出,2-3树的一些性质;

  1. 2-3树全部子叶节点都在同一层
  2. 1个节点能够有1到2个数据,若是有三个须要调整树结构
  3. 1个节点1个数据时,则有两个子节点
  4. 1个节点2个数据时,则有三个子节点,且中间子节点是介于两个节点间的值

2. 数据插入

接下来咱们就模拟在二叉搜索树中退化成链表的数据,插入到2-3树的变化过程,数据包括;一、二、三、四、五、六、7,插入过程图以下;

公众号:bugstack虫洞栈 & 数据插入过程图

以上,就是整个数据在插入过程当中,2-3树的演化过程,接下来咱们具体讲解每一步的变化;

  • α,向节点1插入数据2,此时为了保持平衡,不会新产生分支,只会在一个节点中存放两个节点。
  • β,继续插入数据3,此时这个节点有三数据,一、二、3,是一个临时区域。
  • γ,把三个数据的节点,中间节点拉起来,调整成树形结构。
  • δ,继续插入数据4,为了保持树平衡,会插在节点3的右侧。
  • ε,继续插入数据5,插入后三、四、5共用1个节点,当一个节点上有三个数据时候,则须要进行调整。
  • ζ,中间节点4向上⏫调整,调整后,1节点在左、3节点在中间、5节点在右。
  • η ,继续插入数据6,在保持树平衡的状况下,与节点5公用。
  • θ ,继续插入数据7,插入后,节点7会与当前的节点 5 6 共用。此时是一个临时存放,须要调整。初步调整后,抽出6节点,向上存放,变为2 4 6共用一个节点,这是一个临时状态,还须要继续调整。
  • ι,由于根节点有三个数据二、四、6,则继续须要把中间节点上移,一、3五、7 则分别成二叉落到节点2节点6上。

🇬🇷希腊字母:α(阿尔法)、 β(贝塔)、γ(伽马)、δ(德尔塔)、ε(伊普西隆)、ζ(截塔)、η(艾塔)、θ(西塔)、ι(约塔)

3. 数据删除

有了上面数据插入的学习,在看数据删除其实就是一个逆向的过程,在删除的主要包括这样两种状况;

  1. 删除了3-节点,也就是包含两个数据元素的节点,直接删除便可,不会破坏树平衡。
  2. 删除了2-节点,此时会破坏树平衡,须要将树高缩短或者元素合并,恢复树平衡。

承接上面👆的例子,咱们把数据再从七、六、五、四、三、二、1顺序删除,观察2-3树的结构变化,以下;

公众号:bugstack虫洞栈 & 数据删除过程图

  • α,删除节点7,由于节点7只有一个数据元素,删除节点五、6合并,但此时破坏了2-3树的平衡性,须要缩短树高进行调整。
  • β,由于删除节点后,整个树结构不平衡,因此须要缩短树高,调整元素。节点二、4合并,节点一、3分别插入左侧和中间。
  • γ,删除节点6,这个节点是3-节点(能够分出3个叉的意思),删除后不会破坏树平衡,保持不变。
  • δ,删除节点5,此时会破坏树平衡,须要把跟节点4下放,与3合并。
  • ε,删除节点4,这个节点依旧是3-节点,因此不须要改变树结构。
  • ζ,删除节点3,此时只有一、2节点,须要合并。
  • η ,删除节点2,此时节点依旧是3-节点,因此不须要改变树结构。

再看一个稍微复杂点2-3树删除:

公众号:bugstack虫洞栈 & 复杂树删除过程

上面👆这张图,就一个稍微复杂点的2-3平衡树,树的删除过程主要包括;

  1. 删除4,其实须要将节点三、5合并,指向节点2,保持树平衡。
  2. 删除7,节点八、9合并。
  3. 删除14,节点15上移,恢复成3-叉树。

🤔若是有时候很差理解删除,能够试想下,这个要删除的节点,在插入的时候是一个什么效果。

4. 数据索引

相比于插入和删除,索引的过程仍是比较简单的,不须要调整数据结果。基本原则就是;

  1. 小于当前节点值,左侧寻找
  2. 大于当前节点值,右侧寻找
  3. 一直到找到索引值,中止。

🔍第一层寻找:

🔍第二层寻找:

🔍第三次寻找:

5、总结

  • 综上讲解了2-3树🌲的核心内容,经过本章节的学习,能够了解2-3树是一种怎样的数据结构、如何插入数据、删除数据以及数据的索引,同时要知道这是一种平衡树的结构,包括2-叉和3-叉节点以及数结构随着数据的添加删除调整。
  • 2-3树是红黑树的演变前身,经过这一章节的学习就很容易学习红黑树的相关知识,在红黑树中添加数据进行的渲染、旋转等来保持树平衡。红黑树接近平衡
  • 数据结构方面的知识学习起来,可能会比较🤯烧脑,由于须要思考出那种模型结构和变化的过程,因此会感受困难。但这个烧脑的过程也是对学习很是有帮助的,能够迅速建设知识凸起,当突破不理解到理解,能够有很是多的收获。

6、系列推荐