其他分享
首页 > 其他分享> > 数据结构之红黑树。2-3-4树

数据结构之红黑树。2-3-4树

作者:互联网

2-3-4树

红黑树其实是由2-3-4树演变来的,如果想要理解红黑树,可以先看看2-3-4树,其特点如下:

2-3-4树中结点添加需要遵守以下规则:

接下来我们模拟一下,像一个2-3-4树中插入:

  1. 插入 1 ,不用任何特殊处理
    在这里插入图片描述

  2. 插入 2,不用任何处理:
    在这里插入图片描述

  3. 插入 3 ,首先临时变为一个4节点,然后进行升元:
    4.
    在这里插入图片描述
    可以看到,中间元素进行2升元,这时候树依然满足2-3-4树规则。

  4. 插入元素 4 ,不用进行任何处理:
    在这里插入图片描述

  5. 插入元素5,这时候需要进行升元,将元素4升元:
    在这里插入图片描述

  6. 插入元素6,不需要额外处理:
    在这里插入图片描述

  7. 插入元素7,这时候 5 6 7是一个4节点,需要升元:
    在这里插入图片描述

  8. 插入元素8,不用进行任何处理:
    在这里插入图片描述

  9. 插入元素9,这时候,7 8 9需要进行升元:
    在这里插入图片描述

  10. 插入元素10,不需要额外处理:
    在这里插入图片描述

  11. 插入元素11,9 10 11需要进行升元:
    在这里插入图片描述
    可以看到,通过2-3-4树的性质、升元操作,一颗2-3-4树,总是能够保持相对的平衡。

红黑树

红黑树属于二叉搜索树,但是每个节点增加了一个存颜色的位,它的规则是:

红黑树保证了最长路径不超过最短路径的两倍,没有AVL树那么严格的平衡,但是旋转少效率高,也是O(LgN)。AVL树追求的是极致平衡,当你插入一个元素时,旋转的次数不能预估,当插入、删除特别频繁时,树就会不停地旋转,严重影响效率。

红黑树插入时对应2-3-4树规则如下:

一个节点2-3-4树和红黑树表示如下:
在这里插入图片描述

2个节点的2-3-4树和红黑树表示如下:

在这里插入图片描述

3个节点的2-3-4树和红黑树表示如下:
在这里插入图片描述

可以很明显的看到,红黑树中,每个黑色节点和其红色子节点就是对应到了红黑树中一个节点,在2-3-4树中,就是黑色节点和其红色节点是在同一层的。

红黑树中插入节点规则如下:

红黑树保证了最长路径不超过最短路径的两倍,没有AVL树那么严格的平衡,但是旋转少效率高,也是O(LgN)。AVL树追求的是极致平衡,当你插入一个元素时,旋转的次数不能预估,当插入、删除特别频繁时,树就会不停地旋转,严重影响效率。

红黑树插入时,如果父节点是黑色,那么是不需要任何处理的,这时候实际上对应2-3-4树就是节点是一个2节点,直接加入即可

其它几种状况处理:

  1. 当前节点的父节点是红色,且当前节点的祖父节点的另一个子节点(叔叔节点)也是红色。

在这里插入图片描述

这种情况下不需要旋转,只需要变色即可

  1. 当前节点的父节点是红色,叔叔节点不存在或叔叔节点为黑色,且父节点是爷爷节点的左子节点,同时当前节点也是父节点的左子节点,当前节点与父节点都是左节点
    这时候也就是LL型,
    比如 3-2,这时候插入 1,变成 3-2-1,
    在这里插入图片描述在这里插入图片描述

这时候,如果不进行调整的话,那么这个2-3-4节点就不满足2-3-4要求,那么调整逻辑就是,按照顺序排列,中间节点2可以作为新的顺序节点,调整后,让节点恢复标准 2-3-4节点:
在这里插入图片描述
对应红黑树为: 在这里插入图片描述
而操作过程如下:
(1)将插入节点父节点变色
(2)以插入节点父节点为轴旋转

在这里插入图片描述

  1. 当前节点的父节点是红色,叔叔节点不存在或叔叔节点为黑色,且父节点是爷爷节点的左子节点,同时当前节点是父节点的右子节点,
    这就是所谓的LR型,这时候,对应2-3-4树如下:
    在这里插入图片描述
    对应红黑树如下:
    在这里插入图片描述
    这时候我们要恢复到标准的2-3-4结构:
    在这里插入图片描述
    操作思路则是先将LR变为LL,然后在像LL一样操作即可。
    (1)首先将 1 节点左旋,也就是插入节点的父节点左旋,变为LL 型
    (2)按照LL型旋转操作
    在这里插入图片描述
  2. 当前节点的父节点是红色,叔叔节点不存在或叔叔节点为黑色,且父节点是爷爷节点的右子节点,同时当前节点也是父节点的右子节点,即插入节点与其父节点都是右子节点
    这时候对应2-3-4树如下:
    在这里插入图片描述

对应红黑树如下:
在这里插入图片描述
这时候还是不满足2-3-4树的性质,需要调整,调整如下:
(1) 父节点变为黑色,爷爷节点变为红色
(2)爷爷节点为轴,左旋:
在这里插入图片描述
这样操作之后,能够满足2-3-4树和红黑树的特质。

  1. 当前节点的父节点是红色,叔叔节点不存在或叔叔节点为黑色,且父节点是爷爷节点的右子节点,当前节点是父节点的左子节点
    即所谓的RL型。
    这时候对应2-3-4树如下:
    在这里插入图片描述
    对应红黑树为:
    在这里插入图片描述

这时候先将RL转换RR,然后按照RR操作:
(1)当前节点父节点右旋,变为RR,然后按照RR操作:
(2) 父节点变为黑色,爷爷节点变为红色
(3)爷爷节点为轴,左旋:
在这里插入图片描述

这就是原理性的指导,代码实现我们可以参考下java中TreeMap的实现:

private void fixAfterInsertion(Entry<K,V> x) {
        x.color = RED;
		// 必须是父节点是红色节点才会调整,黑色节点不需要
        while (x != null && x != root && x.parent.color == RED) {
            // 父节点是爷爷节点的左子节点
            if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
                Entry<K,V> y = rightOf(parentOf(parentOf(x)));
                // 叔叔节点是红色,直接变色,不需要旋转
                if (colorOf(y) == RED) {
                    setColor(parentOf(x), BLACK);
                    setColor(y, BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    x = parentOf(parentOf(x));
                } else {
                   // 当前节点还是父节点的右子节点,LR型,旋转,变为LL型
                    if (x == rightOf(parentOf(x))) {
                        x = parentOf(x);
                        rotateLeft(x);
                    }
                    // LL型处理,将父节点设置为黑色,爷爷节点设置为红色,然后父节点为轴右旋
                    setColor(parentOf(x), BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    rotateRight(parentOf(parentOf(x)));
                }
            } else {
            	// 这时候父节点是爷爷节点的左子节点
                Entry<K,V> y = leftOf(parentOf(parentOf(x)));
                // 叔叔节点是红色,不需要调整,直接变色即可
                if (colorOf(y) == RED) {
                    setColor(parentOf(x), BLACK);
                    setColor(y, BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    x = parentOf(parentOf(x));
                } else {
                	// 当前节点是父节点的左子节点,RL型,先旋转为RR型
                    if (x == leftOf(parentOf(x))) {
                        x = parentOf(x);
                        rotateRight(x);
                    }
                    // RR型,将父节点设置为黑色,爷爷节点设置为红色,以父节点为轴,左旋
                    setColor(parentOf(x), BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    rotateLeft(parentOf(parentOf(x)));
                }
            }
        }
        root.color = BLACK;
    }


private void rotateRight(Entry<K,V> p) {
        if (p != null) {
            Entry<K,V> l = p.left;
            p.left = l.right;
            if (l.right != null) l.right.parent = p;
            l.parent = p.parent;
            if (p.parent == null)
                root = l;
            else if (p.parent.right == p)
                p.parent.right = l;
            else p.parent.left = l;
            l.right = p;
            p.parent = l;
        }
    }
private void rotateLeft(Entry<K,V> p) {
        if (p != null) {
            Entry<K,V> r = p.right;
            p.right = r.left;
            if (r.left != null)
                r.left.parent = p;
            r.parent = p.parent;
            if (p.parent == null)
                root = r;
            else if (p.parent.left == p)
                p.parent.left = r;
            else
                p.parent.right = r;
            r.left = p;
            p.parent = r;
        }
    }

算法演示: https://www.cs.usfca.edu/~galles/visualization/RedBlack.html

标签:黑树,之红,结点,parentOf,parent,插入,红黑树,数据结构,节点
来源: https://blog.csdn.net/LeoHan163/article/details/122472182