红黑树C++实现

来源:互联网 发布:重庆网络监测公司 编辑:程序博客网 时间:2024/05/24 07:17

看算法导论看的有点晕,代码的缩进让我直接抓狂了,网上找了一个比较靠谱的解法,链接

 

现在具体分析一下插入操作:
1. 首先父亲节点如果是黑色节点的话,不需要处理了,多一个红色节点不会有任何影响.
2. 如果父亲节点是红色的,而叔父节点也是红色,那就是把父亲和叔父节点同时改成黑色,祖父改为红色,然后递归的向上传递.
3. 如果父亲节点是红色的,而叔父节点是黑色的. 后面的话比较拗口.父亲是祖父的左孩子.
   (1)如果自己是父亲的孩子,那么修改父亲为黑色,祖父为红色,然后右转祖父
   (2)如果自己是父亲的孩子,那么先把自己指向父亲,再做左转自己,执行(1).

4. 如果父亲是祖父的右孩子

    (1)如果自己是父亲的孩子,那么修改父亲为黑色,祖父为红色,然后左转祖父
    (2)如果自己是父亲的孩子,那么先把自己指向父亲,再做右转自己,执行(1).

(以上转自上述网页,并根据网页中的代码对描述作了适当的修改)。

对应的代码如下:

 

 

现在来看看红黑树的删除操作:

在这里先暂且复习一下树中节点x的后继操作:

1. 如果x含有右子,则返回右子中的最小值(不停地遍历右子的左枝)

2. 没有右子,令x的父节点为y,如果x是y的左子,则直接返回y

3. x是y的右子,则迭代{x = y;y=y->father;}直到y为空或者x是y的右子为止。

代码如下:

 

另外简单证明一下二叉树节点node的后继无左子的定理:

反证法:

假设node的后继successor有左子left:

1. 如果node.value<left.value

    则node的后继为left而非successor

2. 如果node.value>left.value

    则left不可能为successor的左子树(因为如果left的value比node要小,则left必在node的左子树中,而node的后继一定大于node,一定不在node的左子树中)

矛盾。因此定理成立。

 

 

现在分析一下红黑树的删除操作,以下为了表示简便,F代表父节点,S代表兄弟节点,x表示当前节点:

1. 如果x不为根并且x为黑色,执行2,否则执行6。

2. 如果x为右子,执行5,否则:

     如果S为黑,执行3,否则:

        置S为黑,F为红,左旋F,并更新S为F的右子

3. 如果S的两子均为黑,置S为红,x更新为F,执行1;
    否则执行4

4. 这里分两种情况:

    4.1 如果S的右子为黑,S的左子也置黑,S置红,S更新为F的右子,否则直接执行4.2

    4.2 S的颜色置为F的颜色,F置黑,S右子置黑,左旋F,x更新为root,执行6

5. 和2-4对称,只需要把left换为right即可

6. 置x为黑色(x为根或者x为红色)

 

这个说起来还是很绕口,其实就是删除一个红节点不影响树的红黑性质,但是删除树的黑节点则会影响以下三点:

1 具有等同黑高的性质

2 如果删除了x,而x的孩子和父亲都为红色,则违反了红节点只能有黑孩子的性质

3 如果x只有一个红孩子,则x为根,删除了x会破坏根为黑色的性质。

根据以上的讨论,需要检查被删除节点的孩子的情况。

 

所有的代码如下:

 

原创粉丝点击