你能听懂的红黑树的插入和删除

红黑树

红黑树是一种自平衡的二叉查找树,是一种高效的查找树。红黑树具有良好的效率,它可在 O(logN) 时间内完成查找、增加、删除等操作。因此,红黑树在业界应用很广泛,比如 Java 中的 TreeMap,JDK 1.8 中的 HashMap、C++ STL 中的 map 均是基于红黑树结构实现的。

性质:

根节点为黑色

无相邻的红节点

根节点到任意叶节点路径,所含黑色节点数量相同

插入

插入为根节点,则变黑

插入为红叶节点,看叔节点,叔节点为红,则上三角反色

你能听懂的红黑树的插入和删除_第1张图片

叔节点为黑,向上的三个节点(包含插入节点在内向上的三个节点)重组为上三角,且满足黑根红叶,重组时将中间值向上提为黑根,剩余节点为红。最后左给左,右给右。

你能听懂的红黑树的插入和删除_第2张图片

首先将26、25、27三角形反色

你能听懂的红黑树的插入和删除_第3张图片

按照中间值向上提之后就变成下面这样

你能听懂的红黑树的插入和删除_第4张图片

此时26原来的子节点就按照左给左、右给右

你能听懂的红黑树的插入和删除_第5张图片

删除

删除节点分为两种情况

  1. 删除节点为红色节点,直接删除即可
  2. 删除节点为黑色节点,分为三种情况
    1. 删除有2个红色子节点的黑色节点,找到删除节点的前驱或者后继节点,进行数据交换,然后删除前驱或者后继节点
    2. 删除有1个红色子节点的黑色节点,直接删除节点,将子节点移动到删除节点的位置,并继承删除节点的颜色
    3. 黑色叶子节点,又分为三种情况
      1. 删除节点为根节点,直接删除,特别注意这里是结合删除的是黑色叶子节点的,意味着这种情况只有一个根节点,且为黑色
      2. 删除节点的兄弟节点为黑色,分为两种情况
        1. 兄弟节点有红色子节点,借用兄弟子节点修复,如果是LL则右旋父节点,RR则左旋父节点,LR或者RL都是双旋,先左旋(右旋)兄弟节点,然后右旋(左旋)父节点。有两个红色子节点的话,可以自己选择修复方式。
        2. 兄弟节点没有红色子节点(父节点向下合并),分为两种情况
          1. 父节点为红色,直接删除节点,父节点设置为黑色,兄弟节点设置为红色,具体参考234树种的下溢情况,下溢之后,才会这样变色
          2. 父节点为黑色,先下溢,下溢之后变色,其次将父节点假作删除节点进行递归删除操作
      3. 删除节点的兄弟节点为红色(转换为黑色处理),先对父节点进行旋转,如果被删除节点在右边则右旋,反之同理。旋转之后变色,将被删除节点的兄弟节点设置为黑色,父节点设置为红色(这个变色跟2.3.2.2是不同的),此时就完成了转换成黑色的情况(注意做完这些之前还没有做删除操作)。完成转换之后再根据现在的情况做删除操作,此时的父节点一定为黑色。

示例红黑树

你能听懂的红黑树的插入和删除_第6张图片

情况2.1(对应上面的情况)

这里比如我们删除5这个节点,此时它有两个红色子节点,我们需要找到它的前驱或者后继节点其中之一,比如这里是前驱节点,我们交换删除节点和前驱节点的数据,然后将前驱节点原来的位置节点直接删除,就成了下面这样

你能听懂的红黑树的插入和删除_第7张图片

情况2.2

比如我们现在在情况2.1的基础上删除0节点,它只有一个红色子节点,此时我们可以删除节点,将它唯一的红色子节点移动到删除节点的位置,然后将红色子节点染色为删除节点的颜色

你能听懂的红黑树的插入和删除_第8张图片

情况2.3.1

太简单,省略

情况2.3.2.1右旋

这里还是基于情况2.2的树,这次我们看另外一边,46为删除的目标节点

你能听懂的红黑树的插入和删除_第9张图片

这种情况,目标节点的兄弟节点为黑色,且有一个红色子节点,删除46之后就形成了一个LL的情况(37为43的左子节点,32为37的左子节点),此时我们只需要围绕父节点进行右旋,不知道右旋的朋友去看平衡二叉树先,右旋之后,上去的节点需要继承父节点颜色,且下面的节点都需要变成黑色,变成下面这样

你能听懂的红黑树的插入和删除_第10张图片

情况2.3.2.1双旋

我们换成这个图,46还是目标删除节点

你能听懂的红黑树的插入和删除_第11张图片

此时删除46之后,形成LR情况(37为43的左子节点,39为37的右子节点),此时我们需要先围绕目标节点的兄弟节点进行左旋,左旋还是右旋,根据是LR还是RL,LR先左旋,再右旋。

你能听懂的红黑树的插入和删除_第12张图片

围绕兄弟节点旋转之后,我们围绕父节点进行旋转,上去的节点继承父节点颜色,下来的节点变为黑色,平衡完成。

你能听懂的红黑树的插入和删除_第13张图片

情况2.3.2.1左旋

来看这个图,37是目标删除节点

你能听懂的红黑树的插入和删除_第14张图片

删掉37之后形成RR情况,围绕父节点进行左旋,然后上去的节点继承父节点颜色,下来的节点都染色为黑色,平衡完成

你能听懂的红黑树的插入和删除_第15张图片

情况2.3.2.2.1

出现了点问题,现在图稍微改变了一下,目标删除节点是46

你能听懂的红黑树的插入和删除_第16张图片

此时父节点为红色,子节点没有红色子节点,我们只需要删除节点,然后将父节点设置为黑色,兄弟节点设置为红色,平衡完成。

你能听懂的红黑树的插入和删除_第17张图片

情况2.3.2.2.2

我现在将图变成这样,目标删除节点为62

你能听懂的红黑树的插入和删除_第18张图片

此时父节点为黑色了,我们首先需要删除62,然后变色,变色跟2.3.2.2.1一样,父节点设置为黑色,兄弟节点设置为红色

你能听懂的红黑树的插入和删除_第19张图片

这时我们需要将父节点假作是被删除的节点(但是不能真的删除,只是做删除之后的操作)做递归操作,假如54是被删除节点,此时它的兄弟节点为黑色,且有一个红色子节点,且为LL的情况,右旋兄弟节点。

你能听懂的红黑树的插入和删除_第20张图片

情况2.3.2.3

目标删除节点20

你能听懂的红黑树的插入和删除_第21张图片

兄弟节点为红色,此时我们删除节点20,然后对父节点节点进行左旋变色,删除节点的父节点设置为红色,兄弟节点设置为黑色

你能听懂的红黑树的插入和删除_第22张图片

记住这个nil节点,这个节点是如果我们节点20没有被删除之前的位置,此时我们围绕这个节点做后续操作,兄弟节点已经为黑色,父节点为红色,且兄弟节点有一个红子节点,情况为RL,先对兄弟节点(是此时的兄弟节点,不是原来的)进行右旋

你能听懂的红黑树的插入和删除_第23张图片

之后对父节点进行左旋并变色,上去的节点变为红色,下面的变为黑色

你能听懂的红黑树的插入和删除_第24张图片

参考学习:

  • https://www.bilibili.com/video/BV1xG4y1b7Zu/?spm_id_from=333.337.search-card.all.click
  • https://www.bilibili.com/video/BV1Ce4y1Q76H/?spm_id_from=333.337.search-card.all.click&vd_source=d6f2ffe66a51532131343c9b15bb13c9

红黑树在线模拟:https://www.cs.usfca.edu/~galles/visualization/RedBlack.html

原创不易,转载请注明出处。

你可能感兴趣的:(数据结构)