红黑树解析

Posted Doraemon的四次元口袋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了红黑树解析相关的知识,希望对你有一定的参考价值。

一、 二叉查找树 (Binary Search Tree)

二叉查找树(BTS)特点:

  1. 左子树上所有节点的值小于或等于其跟节点的值。

  2. 右子树上所有节点的值大于或等于其跟节点的值。

  3. 左右子树也一定分别为二叉排序树。

下图为该数组的二叉查找树:[9, 5, 13, 2, 7, 11, 15, 1,  3,  6, 8, 10, 12]

查找:

从根节点开始查找,与相应节点比较,如果大于该节点,则向右继续查找;如果小于该节点,则向左继续查找。查找到结果时停止,或者查找到叶节点为止。

列如:查找该组数据中是否含有8 。

8<9(左)   8>5(右)  8>7(右)  -->8

红黑树解析

插入:

从根节点开始比较,如果大于根节点,则向右继续比较;如果小于根节点,则向左继续比较。直到最外层节点时插入。

红黑树解析

删除:

  • 叶节点直接删除,对其他节点无影响。

  • 若只有一个孩子结点(左孩子或者右孩子),则直接让其孩子结点顶替该删除结点;

  • 若有两个孩子结点,则找到该结点的右子树中值最小的叶子结点来顶替该结点,然后删除这个值最小的叶子结点。

删除非叶节点时:

  • 情况1:如果被删除的节点没有右子节点,那么就选择它的左子节点来代替原来的节点。

红黑树解析

红黑树解析

情况 2:如果被删除节点的右节点没有左节点,那么这个右节点被用来替换被删除节点。

红黑树解析

红黑树解析

情况 3:如果被删除节点的右节点有左节点,就需要用被删除节点右节点的左子树中的最下面的节点来替换它。(就是用被删除节点的右节点中的最小值来替换)

红黑树解析

红黑树解析

遍历:

前序遍历:

先访问根节点,再连续遍历左子树直到最小值,最后遍历右子树;并且在遍历左右子树时,仍需先访问父节点,然后遍历左子树,最后遍历右子树。

父结点 ---> 左子树(最小) ---> 右子树

下图前序遍历结果为:[11, 7, 5, 4, 0, 2, 1, 3,  6,  9, 8, 10, 15, 13, 12, 14, 16]

红黑树解析

中序遍历:

先遍历左子树最小节点,然后遍历右子树节点,最后遍历父节点;并且在遍历左右子树的时候,仍然是先遍历左子树,然后访问父节点,最后遍历右子树。(中序遍历可以从小到达排序)

左子树 ---> 父结点 ---> 右子树

上图中序遍历结果为:[0, 1, 2, 3, ,4 ,5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

红黑树解析

后序遍历:

先遍历左子树,然后遍历右子树,最后访问根节点;同样,在遍历左右子树的时候同样要先遍历左子树,然后遍历右子树,最后访问根节点。前图后序遍历结果如下。

左子树 ---> 右子树 ---> 父结点

[1, 3, 2, 0, 4, 6, 5, 8, 10 ,9 ,7, 12, 14, 13, 16, 15, 11]

红黑树解析

缺点:

BST 算法查找时间依赖于树的拓扑结构。最佳情况是 O(log­2n),而最坏情况是 O(n)。

二叉查找树的缺点:BST只有同一个的节点或者同一节点过多的时候,导致左右不平衡,查找效率变低。

红黑树解析

二、 红黑树(Red Black Tree)

红黑树是一种自平衡二叉树查找树,通过旋转与变色达到左右平衡。

红黑树特定(R-B Tree)特点:

  1. 节点是红色或者黑色。

  2. 根节点是黑色。

  3. 每个叶节点都是黑色的空节点(NULL)。

  4. 每个红色节点的两个子节点都是黑色节点(黑色节点的子节点可能是黑色节点)。

  5. 从任意节点到其每个叶节点的所有路径都包含相同个数的黑色节点。

红黑树解析

红黑树的旋转:

左旋转:右子节点替换父节点,父节点作为左节点;原来右子节点的左孩子变为原来父节点的右孩子。

红黑树解析

右旋转:左子节点替换父节点,父节点作为右子节点;原来左子节点的右孩子变为原来父节点的左孩子。

红黑树解析

插入:

红黑树解析

注意:插入的节点默认颜色应为红色(当父节点为黑色时不需要自平衡)。

情况1:红黑树为空树

把插入节点作为根节点,并且把该节点设置为黑色。

情况2:插入节点的key已存在

直接修改节点的值。

例如:已存在一个节点[key:1001, color:black, data:obj1001],即节点key值为1001,节点颜色为黑色,节点中的值为obj1001。

如果插入一个[key:1001, color:red, data:obj1002]的节点,只需要把原节点中的值更新。

情况3:插入节点的父节点为黑色节点:

由于插入的节点是红色的,并不会影响红黑树的平衡,直接插入,无需做自平衡。

红黑树解析

情况4:插入结点的父结点为红结点

插入情景4.1:父节点为红色,叔叔结点为红色

红黑树解析

处理步骤:

4.1.1 把父节点和叔叔节点设置为黑色

红黑树解析

4.1.2 把祖父节点设置为红色

红黑树解析

 4.1.3 在整个红黑树中就变成了下面的情况,后续再把祖父节点(25)当做当前节点,继续判断。

红黑树解析

插入情景4.2:父节点为红色,叔叔节点为黑色或者NUL,并且插入节点的父节点是祖父节点的左子节点

红黑树解析

插入情景4.2.1:插入节点是父节点的左子节点

处理步骤

4.2.1.1:把插入节点的父节点设置为黑色。

红黑树解析

4.2.1.2:把插入节点的祖父节点设置为红色。

红黑树解析

4.2.1.3:把插入节点的祖父节点右旋。

红黑树解析

插入情景4.2.2:插入节点是父节点的右子节点

处理步骤

4.2.2.1 把插入节点的父节点左旋

红黑树解析

4.2.2.2 把插入节点的父节点(15)设置为插入节点,得到情景4.2.1。

4.2.2.3 进行情景4.2.1的处理。

插入情景4.3:叔叔节点为黑色或者nuL,并且插入节点的父节点是祖父节点的右子节点

该情景与4.2类似,只是旋转方向相反。

红黑树解析

插入情景4.3.1:插入节点是父节点的右子节点

4.3.1.1 把插入节点的父节点设置为黑色。

红黑树解析

4.3.1.2 把插入节点的祖父节点设置为红色。

红黑树解析

4.3.1.3 把插入节点的祖父节点左旋。

红黑树解析

插入情景4.3.2:插入节点是父节点的左子节点

处理步骤

4.3.2.1 对插入节点的父节点右旋。

红黑树解析

4.3.2.2 把原来的父节点(6)设置为插入节点,得到情景4.3.1。

4.3.2.3 进行情景4.3.1的处理。

练习:

红黑树解析

红黑树解析

删除:

与插入一样,红黑树只能删除叶节点,删除非叶节点的节点,需要与叶节点进行替换。

替换原则(与二叉查找树相同):要删除的节点只有一个子节点,用子节点替换;要删除的节点有两个子节点,用后继节点(大于删除节点的最小节点)替换;

如下图,删除1节点时,遵循二叉树替换情景2,只有一个子节点,那么用子节点(6)替换删除节点(1),然后再删除替代节点(原节点6)。虽然目标是删除黑色1节点,但黑色1节点只是被红色6节点替换,因此实际删除的是原来的红色6节点。

红黑树解析

如下图,删除17节点时,遵循二叉树替换情景3,有两个子节点,用后继节点(22)替换删除节点,然后再删除替代节点。虽然目标是删除红色17节点,但红色17节点只是被红色22节点替换,因此实际删除的是原来的红色22节点。

红黑树解析

红黑树的删除步骤:

  1. 非叶节点需要根据二叉树替换原则进行位置互换。(互换位置,也要互换颜色)

  2. 根据下列规则删除替换后的节点。

通过二叉树三种删除原则,在替换节点(互换颜色位置)后,删除的始终是叶节点,因此后续说的删除节点始终是实际删除的节点!!!!此时需要判断删除节点是否会影响到红黑树的平衡,判断依据是:

红黑树解析

情景1. 如果删除的节点颜色为红色,则不会影响平衡。

情景2. 如果删除的节点是黑色,则需要进行平衡:

情景2.1 删除节点(8)是其父节点的左子节点

情景2.1.1 删除节点的兄弟节点颜色是红色:

  • 把兄弟节点改为黑色

  • 把父节点改为红色

  • 把父节点左旋

 红黑树解析

情景2.1.2 删除节点的兄弟节点是黑色

  情景2.1.2.1 删除节点的兄弟节点的右子节点是红色,左子节点任意颜色(红、黑、NUL)

  • 把兄弟节点的颜色设置为父节点的颜色

  • 把父节点的颜色设置为黑色

  • 把兄弟节点的右子节点设置为黑色

  • 把父节点左旋

红黑树解析

情景2.1.2.2  删除节点的兄弟节点的右子节点是黑色,左子节点是红色

  • 把兄弟节点设置为红色

  • 把兄弟节点的左子节点设置为黑色

  • 对兄弟节点右旋,得到情景2.1.2.1

  • 按照情景2.1.2.1处理

红黑树解析

情景2.1.2.3 删除节点的兄弟节点的子节点都为黑色

情景2.1.2.3.1 父节点为红色

  • 把兄弟节点设置为红色

  • 把父节点设置为黑色

红黑树解析

情景2.1.2.3.2 父节点为黑色

  • 把兄弟节点设置为红色

  • 把父节点作为新的删除节点进行删除情景处理(只做情景处理,不做位置替换)。递归到根节点时退出。

红黑树解析

红黑树解析

情景2.2:删除节点(25)是其父节点的右子节点

删除情景2.2.1:删除节点的兄弟节点是红节点

  • 把兄弟节点设置为黑色

  • 把父节点设置为红色

  • 把父节点右旋,得到情景2.2.2.3

  • 进行情景2.2.2.3处理

红黑树解析

情景2.2.2:删除节点的兄弟节点是黑节点

情景2.2.2.1:删除节点的兄弟节点的左子节点是红节点,右子节点任意颜色。

  • 把兄弟节点的颜色设置为父节点的颜色

  • 把父节点的颜色设置为黑色

  • 把兄弟节点的左子节点设置为黑色

  • 对父节点右旋

红黑树解析

情景2.2.2.2:删除节点的兄弟节点的左子节点是黑节点,右子节点为红节点。

  • 把兄弟节点设置为红色

  • 把兄弟节点的右子节点设置为黑色

  • 对兄弟节点左旋,得到2.2.2.1

  • 进行情景2.2.2.1处理

红黑树解析

情景2.2.2.3:删除的兄弟节点的子节点都为黑色

情景2.2.2.3.1 父节点为红色

  • 把兄弟节点设置为红色

  • 把父节点设置为黑色

情景2.2.2.3.2 父节点为黑色

  • 把兄弟节点设置为红色

  • 把父节点作为新的删除节点进行删除情景处理(只做情景处理,不做位置替换)




以上是关于红黑树解析的主要内容,如果未能解决你的问题,请参考以下文章

Java - HashTree源码解析 + 红黑树

JAVA集合:TreeMap红黑树深度解析

数据结构-红黑树解析

深度解析红黑树

ConcurrentHashMap源码解析_06 红黑树的代理类(TreeBin)

ConcurrentHashMap源码解析_06 红黑树的代理类(TreeBin)