【算法百题之三十二】红黑树插入删除
大家好,我是Lampard~~
很高兴又能和大家见面了,接下来准备系列更新的是算法题,一日一练,早日升仙!
今天的探讨的问题是:实现红黑树的插入删除功能。
(一)什么是红黑树?
一语而言之,红黑树就是一颗弱平衡的二叉搜索树。二叉搜索树(BST)我知道,二叉平衡树我也知道(AVL),弱平衡的二叉搜索树是什么鬼??
二叉搜索树的性质简单,每个结点有唯一的值,且每一个父节点的值比左子结点的值小,比右子结点的值大。
想深入了解二叉搜索树的同学可以看看这篇博客:
至于弱平衡,我们先来看看红黑树的性质:
- 节点是红色或者黑色
- 根节点是黑色
- 每个叶子的节点都是黑色的空节点(NULL)
- 每个红色节点的两个子节点都是黑色的。
- 从任意节点到其每个叶子的所有路径都包含相同的黑色节点。
关键在于第5点,从任意节点到其每个叶子的所有路径都包含相同的黑色节点。
这一点就说明若每一分支黑色结点为N的情况下,分支最短的情况出现在结点全是黑色的情况下(分支的结点总数量为N),而深度最长则出现在分支红黑相间的情况下(N<总数量<=2N)所以最长的分支不会比最短的分支长一倍,这限制了我们不能把结点们都堆在任意一支,导致头重脚轻的情况,若存在该情况则会通过旋转结点来解决。这是不是和二叉平衡树的任意分支的高度差不能超过1,否则就要旋转结点解决有异曲同工之妙?其弱平衡的特性就来自于此。这个特点让红黑树无论在增删改查的过程中都具有很高的效率,这点我们往下慢慢探讨。
对于第一次接触红黑树的同学可以看看这一篇博客,简单易懂:
(二)红黑树的插入
红黑树默认插入的都是红色结点,因为插入黑色结点会破坏每一支黑色结点数相同(性质5)的情况。对于插入操作来说我们要分三种情况讨论:
1.作为根节点插入(无父结点)
2.其父结点是黑色
3.其父节点是红色
(1)作为根节点插入(无父结点)
作为红黑树的根节点,为了符合根节点是黑色(性质2),我们只需要把该结点的红色属性改成黑色即可。
(2)其父结点是黑色
因为其父节点是黑色,那么插入红色结点既不会破坏每一支黑色结点数相同(性质5),也不会违背每个红色节点的两个子节点都是黑色的(性质4)。因此我们只需要直接与其父节点的孩子指针相连起来即可。
(3)其父节点是红色,我们要继续往下分两种情况:
- 父节点的兄弟结点为红色
- 父节点的兄弟结点为黑色或者不存在
(3-1)父节点的兄弟结点为红色
- 插入的位置是左左(父节点是祖父节点的左孩子,自己是父节点的左孩子)或者右右:我们需要把其父节点和父节点的兄弟结点变黑,而其祖父结点则变红,然后再进行判断,看祖父的父节点是不是黑色,若是结束,否则递归进行这个操作。
- 插入的位置是左右(父节点是祖父节点的左孩子,自己是父节点的右孩子)或者右左:只比上面多了一步,就是把自己和父节点的位置进行位置交换,使之变成左左或者右右的情况。
(3-2)父节点的兄弟结点为黑色或者不存在
- 插入的位置是左左(父节点是祖父节点的左孩子,自己是父节点的左孩子)或者右右:我们需要首先把父节点和祖父结点的颜色交换(因为父亲的兄弟结点是黑色,所以就没有动它),然后父节点进行右旋
- 插入的位置是左右(父节点是祖父节点的左孩子,自己是父节点的右孩子)或者右左:只比上面多了一步,就是把自己和父节点的位置进行位置交换,使之变成左左或者右右的情况。
(三)红黑树的删除
对于删除操作,我们同样三种情况进行讨论:
1.删除叶子结点
2.删除单枝结点
3.删除有左右孩子的结点
(1)删除叶子结点
A. 删除的是叶子节点且该叶子节点是红色的 ---> 无需修复,因为它不会破坏红黑树的5个特性
B. 删除的是叶子节点且该叶子节点是黑色的 ---> 很明显会破坏特性5,需要修复。
(2)删除单枝结点
C. 删除的节点(为了便于叙述我们将其称为P)下面有一个子节点 S,对于这种情况我们通过 将P和S的值交换的方式,巧妙的将删除P变为删除S,S是叶子节点,这样C这种情况就会转 换为A, B这两种情况:
C1: P为黑色,S为红色 ---> 对应 A 这种情况
C2: P为黑色或红色,S为黑色 --- > 对应 B 这种情况
(3)删除有左右孩子的结点
D. 删除的节点有两个子节点,对于这种情况,我们通过将P和它的后继节点N的值交换的方 式,将删除节点P转换为删除后继节点N,而后继节点只可能是以下两种情况:
D1: N是叶子节点 --- > 对应情况 A 或 B
D2: N有一个子节点 ---- > 对应情况 C
所以通过上面的分析我们发现,红黑树节点删除后的修复操作都可以转换为 A 或 B这两种情况,而A不需要修复,所以我们只需要研究B这种情况如何修复就行了。