Пример #1
0
Файл: avl.c Проект: hubugui/ds
static void _remove_rebalance(struct avl *avl, struct avl_node *node, compare cmp)
{
    struct avl_node **parentp;

    for (parentp = NULL; node != NULL; node = node->parent) {
retry:
        SET_HEIGHT(node);
        /* rebalance */
        if (ABS(DIFF_HEIGHT(node)) > 1) {
            if (node->parent)
                parentp = (node == node->parent->left) ? 
                        &node->parent->left : &node->parent->right;
            else
                parentp = &avl->root;
            /* left height > right height */
            if (DIFF_HEIGHT(node) > 0) {
                if (node->left->right)
                    node->left = _left_rotate(node->left);
                *parentp = _right_rotate(node);
                node = (*parentp)->left;
            } else {
                if (node->right->left)
                    node->right = _right_rotate(node->right);
                *parentp = _left_rotate(node);
                node = (*parentp)->right;
            }
            SET_HEIGHT((*parentp));
            goto retry;
        }
    }
}
Пример #2
0
Файл: avl.c Проект: hubugui/ds
static void _insert_rebalance(struct avl *avl, struct avl_node *node, compare cmp)
{
    struct avl_node *leaf, **parentp;

    for (leaf = node, node = node->parent; node != NULL; node = node->parent) {
        /* parent height no change means tree balance still */
        if (node->height == HEIGHT(node))
            return;
        SET_HEIGHT(node);

        /* rebalance */
        if (ABS(DIFF_HEIGHT(node)) > 1) {
            if (node->parent)
                parentp = (node == node->parent->left) ? 
                        &node->parent->left : &node->parent->right;
            else
                parentp = &avl->root;
            if (cmp(leaf->value, node->value) == -1) {
                if (cmp(leaf->value, node->left->value) == 1)
                    node->left = _left_rotate(node->left);
                *parentp = _right_rotate(node);
            } else {
                if (cmp(leaf->value, node->right->value) == -1)
                    node->right = _right_rotate(node->right);
                *parentp = _left_rotate(node);
            }
            SET_HEIGHT((*parentp));
            break;
        }
    }
}
Пример #3
0
static void _fix_after_insertion(ptst_t *ptst, stm_tx *tx, stm_blk *sb, stm_blk *xb, node_t *x) {
    stm_blk *pb, *gpb, *yb, *lub;
    node_t  *p, *gp, *y;

    SET_COLOUR(x, RED);
    // rebalance tree
    set_t * s = (set_t*)READ_OBJ(sb);
    while (xb != NULL && GET_PARENT(x) != NULL) {
        pb = GET_PARENT(x);
        p = READ_OBJ(pb);
        if (IS_BLACK(p)) // case 2 - parent is black
            break;

        gpb = GET_PARENT(p);
        gp = READ_OBJ(gpb);
        lub = GET_LEFT(gp);

        if (pb == lub) {
            // parent is red, p=GET_LEFT(g)
            yb = GET_RIGHT(gp); // y (uncle)
            y  = READ_OBJ(yb);
            if (IS_RED(y)) {
                // case 3 - parent is red, uncle is red (p = GET_LEFT(gp))
                p = WRITE_OBJ(pb);
                y = WRITE_OBJ(yb);
                gp = WRITE_OBJ(gpb);
                SET_COLOUR(p, BLACK);
                SET_COLOUR(y, BLACK);
                SET_COLOUR(gp, RED);
                xb = gpb;
                x  = gp;
            } else {
                // parent is red, uncle is black (p = GET_LEFT(gp))
                if ( xb == GET_RIGHT(p) ) {
                    // case 4 - parent is red, uncle is black, x = GET_RIGHT(p), p = GET_LEFT(gp)
                    xb = pb;
                    x  = WRITE_OBJ(pb);
                    _left_rotate(ptst, tx, sb, xb, x);
                    pb=GET_PARENT(x);
                }
                // case 5 - parent is red, uncle is black, x = GET_LEFT(p), p = GET_LEFT(gp)
                p  = WRITE_OBJ(pb);
                gpb = GET_PARENT(p);
                gp  = WRITE_OBJ(gpb);
                SET_COLOUR(p, BLACK);
                SET_COLOUR(gp, RED);
                if (gp != NULL) {
                    _right_rotate(ptst, tx, sb, gpb, gp);
                }
            }
        } else {
            // parent is red, p = GET_RIGHT(gp)
            yb = lub;
            y  = READ_OBJ(yb);
            if (IS_RED(y)) {
                // case 3 - parent is red, uncle is red (p = GET_RIGHT(gp))
                p = WRITE_OBJ(pb);
                y = WRITE_OBJ(yb);
                gp = WRITE_OBJ(gpb);
                SET_COLOUR(p, BLACK);
                SET_COLOUR(y, BLACK);
                SET_COLOUR(gp, RED);
                xb = gpb;
                x  = gp;
            } else {
                // parent is red, uncle is black (p = GET_RIGHT(gp))
                if ( xb == GET_LEFT(p) ) {
                    // case 4 - parent is red, uncle is black, x = GET_LEFT(p), p = GET_RIGHT(gp)
                    xb = pb;
                    x  = WRITE_OBJ(pb);
                    _right_rotate(ptst, tx, sb, xb, x);
                    pb = GET_PARENT(x);
                }
                // case 5 - parent is red, uncle is black, x = GET_RIGHT(p), p = GET_RIGHT(gp)
                p  = WRITE_OBJ(pb);
                gpb = GET_PARENT(p);
                gp  = WRITE_OBJ(gpb);
                SET_COLOUR(p, BLACK);
                SET_COLOUR(gp, RED);
                if(gp != NULL) {
                    _left_rotate(ptst, tx, sb, gpb, gp);
                }
            }
        }
    }

    s = (set_t*)READ_OBJ(sb);
    stm_blk * rob = GET_ROOT(s);
    node_t * ro = READ_OBJ(rob);
    if (IS_RED(ro)) {
        ro = WRITE_OBJ(rob);
        SET_COLOUR(ro,BLACK);
    }
}
Пример #4
0
static void _fix_after_deletion(ptst_t *ptst, stm_tx *tx, stm_blk *sb, stm_blk *xb, node_t *x) {
    stm_blk *pb, *plb, *sibb, *siblb, *sibrb;
    node_t *p, *sib, *sibl, *sibr;
    set_t *s;

    while (GET_PARENT(x)!=NULL && IS_BLACK(x)) {
        pb = GET_PARENT(x);
        p  = WRITE_OBJ(pb);
        plb = GET_LEFT(p);
        if ( xb == plb ) {
            sibb = GET_RIGHT(p);
            sib  = WRITE_OBJ(sibb);
            if (IS_RED(sib)) {
                SET_COLOUR(sib, BLACK);
                SET_COLOUR(p, RED);
                _left_rotate(ptst, tx, sb, pb, p);
	            pb = GET_PARENT(x);
                p=WRITE_OBJ(pb);
                sibb = GET_RIGHT(p);
                sib  = WRITE_OBJ(sibb);
            }

            siblb = GET_LEFT(sib);
            sibl  = READ_OBJ(siblb);
            sibrb = GET_RIGHT(sib);
            sibr  = READ_OBJ(sibrb);
            if (IS_BLACK(sibl) && IS_BLACK(sibr)) {
                SET_COLOUR(sib, RED);
                xb = GET_PARENT(x);
                x  = WRITE_OBJ(xb);
            } else {
                if (IS_BLACK(sibr)) {
                    sibl = WRITE_OBJ(siblb);
                    SET_COLOUR(sibl, BLACK);
                    SET_COLOUR(sib,RED);
                    _right_rotate(ptst, tx, sb, sibb, sib);
                    pb = GET_PARENT(x);
                    p  = WRITE_OBJ(pb);
                    sibb = GET_RIGHT(p);
                }

                sib  = WRITE_OBJ(sibb);
                SET_COLOUR(sib, GET_COLOUR(p));
                p  = WRITE_OBJ(pb);
                SET_COLOUR(p, BLACK);
                sibrb = GET_RIGHT(sib);
                sibr  = WRITE_OBJ(sibrb);
                SET_COLOUR(sibr, BLACK);
                _left_rotate(ptst, tx, sb, pb, p);
                s = (set_t*)READ_OBJ(sb);
                xb = GET_ROOT(s);
                x  = WRITE_OBJ(xb);
                break;
            }
        } else  { // inverse
            sibb = plb;
            sib  = WRITE_OBJ(sibb);
            if (IS_RED(sib)) {
                SET_COLOUR(sib, BLACK);
                SET_COLOUR(p, RED);
                _right_rotate(ptst, tx, sb, pb, p);
                pb = GET_PARENT(x);
                p=WRITE_OBJ(pb);
                sibb = GET_LEFT(p);
                sib  = WRITE_OBJ(sibb);
            }

            siblb = GET_LEFT(sib);
            sibl  = READ_OBJ(siblb);
            sibrb = GET_RIGHT(sib);
            sibr  = READ_OBJ(sibrb);
            if (IS_BLACK(sibl) && IS_BLACK(sibr)) {
                SET_COLOUR(sib, RED);
                xb = GET_PARENT(x);
                x  = WRITE_OBJ(xb);
            } else {
                if (IS_BLACK(sibl)) {
                    sibr = WRITE_OBJ(sibrb);
                    SET_COLOUR(sibr, BLACK);
                    SET_COLOUR(sib, RED);
                    _left_rotate(ptst, tx, sb, sibb, sib);
                    pb = GET_PARENT(x);
                    p  = WRITE_OBJ(pb);
                    sibb = GET_LEFT(p);
                }

                sib = WRITE_OBJ(sibb);
                SET_COLOUR(sib, GET_COLOUR(p));
                p  = WRITE_OBJ(pb);
                SET_COLOUR(p, BLACK);
                siblb = GET_LEFT(sib);
                sibl = WRITE_OBJ(siblb);
                SET_COLOUR(sibl, BLACK);
                _right_rotate(ptst, tx, sb, pb, p);
                s = (set_t*)READ_OBJ(sb);
                xb = GET_ROOT(s);
                x  = WRITE_OBJ(xb);
                break;
            }
        }
    }

    if(IS_RED(x)) {
        SET_COLOUR(x, BLACK);
    }
}//fix_after_deletion