数据结构树-->红黑树

本文深入探讨了红黑树的插入和删除原理,解释了如何通过变色和旋转保持红黑树的自平衡。在插入部分,详细列举了不同插入情况及对应的平衡调整策略;在删除部分,阐述了寻找替换节点和删除后的平衡方法。通过实例展示了红黑树在插入和删除操作中如何维护其特性,确保最长路径不超过最短路径的两倍,从而提高查找效率。
摘要由CSDN通过智能技术生成

目录

1. 数据结构树–>树基础
2. 数据结构树–>二叉树
3. 数据结构树–>二叉查找树\二叉排序树
4. 数据结构树–>平衡二叉树
5. 数据结构树–>霍夫曼树
6. 数据结构树–>红黑树
7. 数据结构树–>二叉堆
8. 数据结构树–>B树
9. 数据结构树–>B+树

红黑树

前一篇文章我们了解了平衡二叉树,也知道了平衡二叉树的缺点:大量的插入删除操作影响性能,所以产生了红黑树。

首先:红黑树与平衡二叉树的目的是一样的,都是解决了二叉查找树退化为链表的问题。

平衡二叉树使用的平衡因子,红黑树使用的是几个特性来达到解决二叉查找树退化链表的问题。

1. 红黑树的特性:

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

注意:红黑树的叶子节点指的是 NIL节点,也就是普通树叶子节点的孩子节点。

红黑树图(抄图)

在这里插入图片描述

红黑树没有平衡因子与平衡二叉树没有关系,红黑树的几个特性保证了红黑树从根节点到叶子节点的最长路径不会超过最短路径的2倍。

当红黑树进行插入或者删除时可能破坏红黑树的特性,这就需要我们做出调整来维持红黑树的特性。

2. 红黑树的变色与旋转

2.1 变色

这个好理解,红黑树只有两种颜色,不是黑就红,这里为满足红黑树特性, 当红黑树不满足自平衡时,我们可以通过节点的变色来满足红黑树的自平衡。

2.2 旋转

二叉树的旋转之前我们在平衡二叉树插入删除时已经详细介绍了什么是左旋与右旋,红黑树的左旋与右旋操作与平衡二叉树是一致的,通过旋转来满足红黑树的自平衡。

2.3 总结

红黑树自平衡又变色,有旋转,但什么时候该旋转,什么手该变色呢?红黑树的特性有5点,当我们做插入删除操作时需要判断多种条件来满足自平衡,我们后续会

一步一步详细介绍,前人的基础为我们提供了详细的逻辑与步骤,不用怕麻烦,我们只是把逻辑的代码实现而已。

3. 红黑树的插入

3.1 插入

红黑树的插入操作是和二叉排序树一致的,根据二叉排序树特性,找到插入位置插入节点。

3.2 插入节点变红

根据红黑树的特性与前人的总结,新插入的节点都是红色,这样一般只会破坏特定4,需要修复的不平衡也相比较简单。我们以新插入的节点为判断开始节点,开始判断红黑树的平衡。

3.3 插入后的自平衡

在这里插入图片描述

上图是盗图,清楚明白的标注了插入节点的各种情况需要我们怎么做。

推荐阅读:
红黑树添加和删除节点原理

插入示例:通过插入12 1 9 2 0 11 7 19 4 15 18 5 14 13 10 16 6 3 8 17完成上述所有情形的展示。

3.3.1 插入12

在这里插入图片描述

普通情况: 初始化插入节点为根节点直接涂黑。

3.3.2 插入1

在这里插入图片描述

普通情况: 插入节点的父节点为黑色,直接插入,无需自平衡。

3.3.3 插入9

在这里插入图片描述

插入完成后节点9变红色,红黑树不平衡:

情况2: 父节点红色父节点是祖父节点的左支:叔叔节点为黑色,插入节点是父节点的右支------> 父节点左旋—>父节点1变为当前节点—>

父节点1变为当前节点—>情况1---->父节点与祖父节点颜色互换,祖父节点右旋---->红黑树平衡达到。

3.3.4 插入2

在这里插入图片描述

插入后属于情况3:父节点红色,父节点是祖父节点的左支, 叔叔节点红色------>情况3------> 父节点与叔叔节点变黑,祖父节点变红---->祖父节点变为当前处理节点

------>普通情况:重新判断当前处理节点为根节点—>当前处理节点变黑---->红黑树平衡。

3.3.5 插入0

在这里插入图片描述

普通情况无需调整。

3.3.6 插入11

在这里插入图片描述

普通情况无需调整

3.3.7 插入7

在这里插入图片描述

插入后属于情况6:父节点红色,父节点是祖父节点的右支,叔叔节点为红色----> 父节点与叔叔节点变黑,祖父节点变红,祖父节点变为当前处理节点—>判断祖父节点

---->普通情况无需调整—>红黑树平衡。

3.3.8 插入19

在这里插入图片描述

普通情况无需调整。

3.3.9 插入4

在这里插入图片描述

插入后属于情况4:父节点红色,父节点是祖父节点右支,叔叔节点黑色,插入节点是父节点的左支。

情况4------> 父节点右旋,当前处理节点变为旋转前,前一个处理节点的父节点7------>判断节点7情况5------> 祖父节点颜色互换,祖父节点左旋------>平衡完成。

3.3.10 插入15

在这里插入图片描述

插入后属于情况6----->处理完成,祖父节点变为处理节点---->判断为普通情况无需调整---->红黑树平衡完成

3.3.11 插入18

在这里插入图片描述

插入后判断为情况2---->父节点左旋,处理节点变为节点15------>判断为情况1—>父节点与祖父节点颜色互换,祖父节点右旋----->红黑树平衡。

3.3.12 插入5

在这里插入图片描述

插入后判断节点5,处于情况6---->处理,当前处理节点变为节点4------>判断情况3----->处理,当前节点变为根节点9---->判断情况普通情况---->根节点直接涂黑---->红黑树平衡。

3.3.13 插入14

在这里插入图片描述

判断插入节点14为情况3------>处理—>当前处理节点变为节点18—>判断节点18情况为普通情况无需操作—>红黑树平衡。

3.3.14 插入13

在这里插入图片描述

插入节点13判断为情况1—>父节点与祖父节点颜色交换,祖父节点右旋—>红黑树平衡

3.3.15 插入10

在这里插入图片描述

普通情况无需操作

3.3.16 插入16

在这里插入图片描述

判断节点16为情况6------>处理,节点14变为处理节点---->判断节点14为情况4------>处理,节点18变为处理节点---->判断节点18为情况5---->处理达到红黑树平衡。

3.3.17 插入6

在这里插入图片描述

判断插入节点6为情况2 ------>处理,节点5变为当前处理节点------->判断节点5为情况1------>处理----->红黑树平衡

3.3.18 插入3

在这里插入图片描述

普通情况无需操作。

3.3.19 插入8

在这里插入图片描述

判断插入节点8为情况6---->处理,祖父节6点变为当前处理节点----->判断节点6为情况5----->处理----->红黑树平衡。

3.3.20 插入17

在这里插入图片描述

判断插入节点17为情况5—>处理---->红黑树平衡。

3.4 代码的实现

红黑树插入代码与插入后的平衡其实最好的就是看java源码吗,java中 TreeMap就是最好的例子。

//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 {
                    if (x == rightOf(parentOf(x))) {
                        x = parentOf(x);
                        rotateLeft(x);
                    }
                    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 {
                    if (x == leftOf(parentOf(x))) {
                        x = parentOf(x);
                        rotateRight(x);
                    }
                    setColor(parentOf(x), BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    rotateLeft(parentOf(parentOf(x)));
                }
            }
        }
        root.color = BLACK;
    }

4. 红黑树的删除

红黑树的节点删除逻辑与二叉排序树的删除逻辑是一样的,不同的是怎么才能保证红黑树的自平衡。

4.1 确认开始平衡的节点。

在这里插入图片描述

从上面的逻辑图可以看出,开始平衡的节点重点在于替换节点的是否有左或右孩子,如果有则删除后孩子节点为开始平衡的节点,如果没有则自己为

开始平衡的节点,平衡后删除自己。

4.2 红黑树删除

红黑树删除和插入一样都遵循一定的逻辑,只要我们找到了开始平衡的节点,按照逻辑就能很快重新平衡二叉树

红黑树删除的平衡逻辑

在这里插入图片描述
我们使用插入结束后的红黑树来完成删除的讲解。

4.2.1 删除12

在这里插入图片描述

  1. 判断节点12,有左右子树,则开始查找替换节点,以二叉查找树的删除逻辑,我们查到替换节点为节点13。我们将节点13的数据赋值给节点12,替换节点13重新变为了要删除的节点,同时也能确定替换节点变为了平衡开始节点。
  2. 判断黑色节点13(替换节点)属于情况4------>处理:父节点与兄弟节点颜色交换,兄左子节点涂黑,入接点右旋---->平衡结束。
  3. 删除多余的替换节点。

4.2.2 删除1

在这里插入图片描述

和插入一样,每删除一个都需要条件判断,来完成红黑树平衡,这里不再一步一步尝试。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值