《算法导论》笔记 第13章 13.3 插入

【笔记】


    void rbInsert(NODE *z) {
        NODE *y = nil;
        NODE *x = root;
        while (x != nil) {
            y = x;
            if (z->key < x->key) { x = x->l; }
            else { x = x->r; }
        }
        z->p = y;
        if (y == nil) { root = z; }
        else {
            if (z->key < y->key) { y->l = z; }
            else { y->r = z; }
        }
        z->l = nil;
        z->r = nil;
        z->c = RED;
        rbInsertFixup(z);
    }
    void rbInsertFixup(NODE *z) {
        NODE *y;
        while (z->p->c == RED) {
            if (z->p == z->p->p->l) {// z 的父亲是爷爷的左儿子
                y = z->p->p->r;// z 的叔叔 y
                if (y->c == RED) {// case 1:叔叔是红的
                    z->p->c = BLACK;// 将 z 的父亲与叔叔置为黑
                    y->c = BLACK;
                    z->p->p->c = RED;// 将 z 的爷爷置为红
                    z = z->p->p;// 问题上移两层
                }
                else {
                    if (z == z->p->r) {// case 2:z 是右儿子
                        z = z->p;
                        leftRotate(z);// 左旋,转为 case 3
                    }
                    z->p->c = BLACK;// case 3:z 是左儿子,对z的爷爷做一次右旋即可完成维护
                    z->p->p->c = RED;
                    rightRotate(z->p->p);
                }
            }
            else if (z->p == z->p->p->r) {// z 的父亲是爷爷的右儿子
                y = z->p->p->l;// z 的叔叔 y
                if (y->c == RED) {// case 1:叔叔是红的
                    z->p->c = BLACK;// 将 z 的父亲与叔叔置为黑
                    y->c = BLACK;
                    z->p->p->c = RED;// 将 z 的爷爷置为红
                    z = z->p->p;// 问题上移两层
                }
                else {
                    if (z == z->p->l) {// case 2:z 是左儿子
                        z = z->p;
                        rightRotate(z);// 右旋,转为 case 3
                    }
                    z->p->c = BLACK;
                    z->p->p->c = RED;
                    leftRotate(z->p->p);
                }
            }
        }
        root->c = BLACK;
    }



【练习】


13.3-1 RB-INSERT中假设新插入的节点是红的。注意如果将z着为黑色,则红黑树的性质4)就不会被破坏。那么我们为什么没有选择将z着为黑色呢?

性质5)被破坏。


13.3-2 在将关键字41,38,31,12,19,8插入一棵初始为空的红黑树中之后结果树是什么样子?



13.3-3 假设3种情景中子树αβγδε的黑高度都是k。标上各个结点的黑高度,以验证图中所示的各种转换能保证性质5)。

case 1:皆为k

case 2:皆为k

case 3:皆为k


13.3-4 证明RB-INSERT-FIXUP永远不会将nil的COLOR设置为RED。

case 1:将z的爷爷置为红,考虑z的爷爷为nil的情况,则z为root的儿子,而在该情况下,root不是nil的儿子,因此不会进入任何case中。

case 2、3:对z的爷爷做一次右旋并染为红,若z的爷爷为nil,与case 1同样的原因,不会出现这种情况。

综上,nil永远不会被设置为RED。


13.3-5 考虑用RB-INSERT插入n个结点而成的一棵红黑树。证明:如果n>1,则该树至少有一个红结点。

当n==2时,不进行维护,该树有一个红叶子结点。

假设n==k-1时,至少有一个红结点。

当n==k时,case 1中,一黑三红变为两黑两红,至少有两个红结点;case 2与case 3中,两红一黑结点数量不变。若有红的根结点被染为黑,仍然剩下至少一个红结点。

因此n>1时该树至少一个红结点。


13.3-6 说明如果红黑树的表示中不提供父指针的话,应当如何有效的实现RB-INSERT。




posted on 2014-04-23 15:23  电子幼体  阅读(963)  评论(0编辑  收藏  举报

导航