红黑树解析
Posted Doraemon的四次元口袋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了红黑树解析相关的知识,希望对你有一定的参考价值。
一、 二叉查找树 (Binary Search Tree)
二叉查找树(BTS)特点:
左子树上所有节点的值小于或等于其跟节点的值。
右子树上所有节点的值大于或等于其跟节点的值。
左右子树也一定分别为二叉排序树。
下图为该数组的二叉查找树:[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(log2n),而最坏情况是 O(n)。
二叉查找树的缺点:BST只有同一个的节点或者同一节点过多的时候,导致左右不平衡,查找效率变低。
二、 红黑树(Red Black Tree)
红黑树是一种自平衡二叉树查找树,通过旋转与变色达到左右平衡。
红黑树特定(R-B Tree)特点:
节点是红色或者黑色。
根节点是黑色。
每个叶节点都是黑色的空节点(NULL)。
每个红色节点的两个子节点都是黑色节点(黑色节点的子节点可能是黑色节点)。
从任意节点到其每个叶节点的所有路径都包含相同个数的黑色节点。
红黑树的旋转:
左旋转:右子节点替换父节点,父节点作为左节点;原来右子节点的左孩子变为原来父节点的右孩子。
右旋转:左子节点替换父节点,父节点作为右子节点;原来左子节点的右孩子变为原来父节点的左孩子。
插入:
注意:插入的节点默认颜色应为红色(当父节点为黑色时不需要自平衡)。
情况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. 如果删除的节点是黑色,则需要进行平衡:
情景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 父节点为黑色
把兄弟节点设置为红色
把父节点作为新的删除节点进行删除情景处理(只做情景处理,不做位置替换)
以上是关于红黑树解析的主要内容,如果未能解决你的问题,请参考以下文章