《算法导论》笔记 第13章 13.4 删除

【笔记】

// 基本没搞懂


    NODE* rbDelete(NODE *z) {
        NODE *y, *x;
        if (z->l == nil || z->r == nil) { y = z; }
        else { y = treeSuccessor(z); }
        if (y->l != nil) { x = y->l; }
        else { x = y->r; }
        x->p = y->p;
        if (y->p == nil) { root = x; }
        else {
            if (y == y->p->l) { y->p->l = x; }
            else { y->p->r = x; }
        }
        if (y != z) {
            z->key = y->key;
            // copy y's satellite data into z
        }
        if (y->c == BLACK) { rbDeleteFixup(x); }
        return y;
    }
    void rbDeleteFixup(NODE *x) {
        NODE *w;
        while (x != root && x->c == BLACK) {
            if (x == x->p->l) {// x 为左儿子
                w = x->p->r;// w 是 x 的兄弟
                if (w->c == RED) {// case 1:w 为红色,必有黑色儿子
                    w->c = BLACK;
                    x->p->c = RED;
                    leftRotate(x->p);
                    w = x->p->r;// x 的新兄弟必为黑色
                }
                if (w->l->c == BLACK && w->r->c == BLACK) {// case 2:x 的兄弟 w 是黑色的,w 的两个儿子都是黑色
                    w->c = RED;// 去掉一重黑色
                    x = x->p;// 以 x 父亲重复 while 循环
                }
                else {
                    if (w->r->c == BLACK) {// case 3:x 的兄弟 w 是黑色的,w 的左儿子是红色的,右儿子是黑色
                        w->l->c = BLACK;// 交换 w 与左儿子的颜色
                        w->c = RED;
                        rightRotate(w);// w 右旋
                        w = x->p->r;// 新兄弟是一个有红色右孩子的黑结点
                    }
                    w->c = x->p->c;// case 4:x 的兄弟 w 是黑色的,而且 w 的右儿子是红色的
                    x->p->c = BLACK;
                    w->r->c = BLACK;
                    leftRotate(x->p);
                    x = root;
                }
            }
            else if (x == x->p->r) {// x 为右儿子
                w = x->p->l;// w 是 x 的兄弟
                if (w->c == RED) {// case 1:w 为红色,必有黑色儿子
                    w->c = BLACK;
                    x->p->c = RED;
                    rightRotate(x->p);
                    w = x->p->l;// x 的新兄弟必为黑色
                }
                if (w->l->c == BLACK && w->r->c == BLACK) {// case 2:x 的兄弟 w 是黑色的,w 的两个儿子都是黑色
                    w->c = RED;// 去掉一重黑色
                    x = x->p;// 以 x 父亲重复 while 循环
                }
                else {
                    if (w->l->c == BLACK) {// case 3:x 的兄弟 w 是黑色的,w 的右儿子是红色的,左儿子是黑色
                        w->r->c = BLACK;// 交换 w 与右儿子的颜色
                        w->c = RED;
                        leftRotate(w);// w 左旋
                        w = x->p->l;// 新兄弟是一个有红色左孩子的黑结点
                    }
                    w->c = x->p->c;// case 4:x 的兄弟 w 是黑色的,而且 w 的左儿子是红色的
                    x->p->c = BLACK;
                    w->l->c = BLACK;
                    rightRotate(x->p);
                    x = root;
                }
            }
        }
        x->c = BLACK;
    }


【练习】

13.4-1 证明:在执行RB-DELETE-FIXUP之后,树根总是黑色的。

循环的退出条件有两个,x为根或x非黑。

当x为根结点时,由case 4可知,x必为黑色。

当x非黑时,循环结束后x会被染成黑色。红黑树的性质得到保持。

因此树根总是黑色的。


13.4-2 证明:在RB-DELETE中,如果x和p[x]都是红色的,则性质4)可以通过调用RB-DELETE-FIXUP(T,x)来恢复。

调用fixup后,x直接被染成黑色并退出。

由RB-DELETE可知,p[x]只有x一个子结点,并且所有经过x的路径都缺少了一个黑结点,将x染为黑色即可保持性质4)。


13.4-3 在练习13.3-2中,我们将关键字41,38,31,12,19,8连续插入一棵初始为空的树中,从而得到一棵红黑树。请给出从该树中连续删除关键字8,12,19,31,38,41后的结果。



13.4-4 在RB-DELETE-FIXUP的哪些行中,可能会检查或修改哨兵nil。


13.4-5 在每种情况中,给出所示子树的根至每个子树α,β,…,ξ之间的黑结点个数,并验证它们在转换之后保持不变。当一个结点的color属性为c或c'时,在计数中可用记号count(c)或count(c')来表示。


13.4-6 证明p[x]在case 1的开头必是黑色的。

若p[x]为红色,则x的兄弟必为黑色,不满足case 1的条件。因此p[x]在case 1开头必为黑色。


13.4-7 假设用RB-INSERT来将一个结点x插入一棵红黑树,紧接着又用RB-DELETE-FIXUP将它从树中删除。结果的红黑树与之前的红黑树是否相同?

不相同,找的图:




posted on 2014-04-24 08:14  电子幼体  阅读(709)  评论(0编辑  收藏  举报

导航