红黑树

作者: 果哥爸 | 来源:发表于2018-05-06 14:29 被阅读67次

    详见: 漫画:什么是红黑树

    一. 二叉查找树(BST)

    A. 原理:

    二叉排序树又称二叉查找树,也称二叉搜索树

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

    • 左子树不空,则左子树上所有的结点值小于或等于它的根结点的值。

    • 右子树不空,则右子数上所有结点值大于或等于它的根节点的值。

    • 左、右子树也分别为二叉排序树

    如图所示就是典型的二叉排序树:

    二叉排序树.png

    B. 优势:

    我们试着查找下值为10结点:

    1. 查看根节点9, 由于10大于9,因此查看右孩子13:

    右孩子13.png

    2. 由于10小于13,因此查看左孩子11:

    左孩子11png

    3. 由于10小于11,因此查看做孩子10,发现10正式要查找的节点:

    结点10.png

    这种方式正式二分查找的思想:查找所需的最大次数等同于二叉查找树的高度。

    插入节点的时候,也是利用类似的方法,通过一层一层比较大小,来找到新节点适合插入的位置

    C. 缺陷:

    但尽管如此,二叉树仍然存在缺陷:

    假设初始的二叉查找树只有三个节点,根节点值为9,左孩子结点值为8,右孩子结点值为12.

    初始二叉查找树.png

    接下来我们依次插入如下五个节点:7,6,5,4,3;依据二叉查找树的特性,得到如图所示:

    image.png

    从图可以看出查找性能大打折扣,几乎变成线性了。

    那如何解决二叉查找树多次插入新结点而导致的不平衡呢?我们的主角红黑树应运而生。

    二. 红黑树

    A. 原理

    红黑树是一种自平衡二叉查找树。除了符合二叉查找树的基本特性外,还具有下列附加特性:

    1.节点是红色或黑色
    2.根节点是黑色
    3.每个叶子节点都是黑色的空节点(NIL节点)
    4.每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
    5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
    

    如图就是一棵典型的红黑树:

    红黑树.png

    正是因为这些规则的限制,才保证红黑树自平衡
    红黑树根到叶子最长路径不会超过最短路径2倍

    插入删除节点的时候,红黑树的规则有可能被打破。这时候就需要做出一些调整,来继续维持我们的规则。

    B. 自平衡

    什么情况下会破坏红黑树的规则,什么情况下不会破坏规则呢?

    举两个简单的 🌰:

    1. 向原红黑树插入值为14新节点:

    image.png

    如图所示,不会破坏红黑树的规则

    2.向原红黑树插入值为21新节点:

    image.png

    由于父节点22红色节点,因此这种情况打破了红黑树规则4(每个红黑树的两个子结点都是黑色),必须进行调整,使之重新符合红黑树的规则。

    调整的方式有两种:变色旋转

    旋转又分成两种形式: 左旋转右旋转

    变色:

    为了重新符合红黑树的规则,尝试把红色节点变成黑色,或者把黑色节点变成红色

    下图所示是原红黑树的一部分,需要注意节点25并非根节点。因为节点21节点22连续出现了红色不符合规则4,所以把节点22红色变成黑色

    image.png

    但是凭空多出的黑色节点打破了规则5,所以需要继续把节点25黑色变成红色:

    image.png

    此时又出现了节点25和节点27两个连续的红色节点,需要继续把节点27红色变成黑色`。

    image.png

    左旋转:

    逆时针旋转红黑树的两个节点,使得父节点被自己的右孩子取代,而自己成为自己的左孩子。

    如图所示:

    左旋转.png

    图中,身为右孩子Y取代了X的位置,而X变成了自己的左孩子。此为左旋转

    右旋转:

    顺时针旋转红黑树的两个节点,使得父节点被自己的左孩子取代,而自己成为自己的右孩子。

    如图所示:

    右旋转.png

    图中,身为左孩子Y取代了X的位置,而X变成了自己的右孩子。此为右旋转

    C. 典型例子

    我们以刚才插入节点21的情况为例:

    插入节点21.png

    首先,我们需要做的就是变色,把节点25及其下方的节点变色:

    变色后.png

    此时节点17节点25是连续的两个红色,如果把节点17变成黑色节点?这样一来不仅打破规则5,而且根据规则2(根节点是黑色),也不可能把节点13变成红色节点

    由此可见,变色已无法解决问题,我们把节点13看做X,把节点17看做Y,像刚才的示意图那样进行左旋转:

    示意图.png 左旋转前.png 左旋转后.png

    由于根节点必须是黑色节点,所以需要变色变色结果如下:

    变色后.png

    这样还没结束,从图中可以看出,其中两条路径(17 -> 8 -> 6 -> NIL)黑色节点个数4,其他路径的黑色节点个数3,不符合规则5

    这时候,我们需要把节点13看做X节点8看做Y,像刚才示意图那样进行右旋转:

    示意图.png 右旋转前.png 右旋转后.png

    最后根据规则变色:

    变色后.png

    如此一来,我们的红黑树变得重新符合规则。这一个例子的调整过程比较复杂,经历了如下步骤:

    变色 -> 左旋转 -> 变色 -> 右旋转 -> 变色
    

    三. 最后

    飞翔.jpeg

    相关文章

      网友评论

          本文标题:红黑树

          本文链接:https://www.haomeiwen.com/subject/glturftx.html