static int map_test(mapnode_t *node) { /* got this routine by Julienne Walker from * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx */ mapnode_t *left, *right; if (node == NIL) return 1; left = node->left; right = node->right; if (IS_RED(node) && (IS_RED(right) || IS_RED(right))) { s_log_note("Red violation on node with key %p\n", node->key); return 0; } int lh = map_test(left); int rh = map_test(right); if (left != NIL && left->key > node->key) { s_log_note("Left node (key: %p) of parent node (key: %p) is incorrectly ordered\n", left->key, node->key); return 0; } if (right != NIL && right->key < node->key) { s_log_note("Right node (key: %p) of parent node (key: %p) is incorrectly ordered\n", right->key, node->key); return 0; } if (lh && rh) return IS_RED(node) ? lh : lh + 1; else return 0; }
void rb_insert_fixup(Node* &T, Node *n) { // 如果n的父亲是红色,则需要调整 // 如果n的父亲是黑色,则不需要调整,因为n本身是红色 while(IS_RED(PARENT(n))) { // 根据n的叔叔节点的颜色,来决定调整方案 Node *p = IS_LEFT(PARENT(n))? RIGHT(PARENT(PARENT(n))): LEFT(PARENT(PARENT(n))); // 如果叔叔是红色,那很简单,把爷爷的黑色转移给父亲和叔叔,爷爷刷成红色 // 这样,即满足了性质4,也没有破坏性质5及其他性质 // 但是,爷爷可能破坏了红黑性质4,则从爷爷开始继续调整(向上递归了两层) if (IS_RED(p)) { // 父亲刷成黑色 SET_BLACK(PARENT(n)); // 叔叔刷成黑色 SET_BLACK(p); // 爷爷刷成红色 SET_RED(PARENT(PARENT(n))); // 从爷爷开始继续调整 n = PARENT(PARENT(n)); continue; } // 如果叔叔是黑色,就复杂一点,引入旋转操作 // 如果n是左孩子,那么需要一次右旋+颜色调整即可 // 如果n是右孩子,则通过一次左旋调整成左孩子,然后按上面情况处理 if (IS_LEFT(PARENT(n))) { // 如果n是右孩子,通过右旋调整成左孩子 if (IS_RIGHT(n)) { n = PARENT(n); left_rotate(T, n); } // 现在n是左孩子了 SET_BLACK(PARENT(n)); SET_RED(PARENT(PARENT(n))); right_rotate(T, PARENT(PARENT(n))); } else { if (IS_LEFT(n)) { n = PARENT(n); right_rotate(T,n); } SET_BLACK(PARENT(n)); SET_RED(PARENT(PARENT(n))); left_rotate(T,PARENT(PARENT(n))); } } // 如果n是根节点,则把根设置为黑色 if (NIL == PARENT(n)) SET_BLACK(n); }
CMD *parseSimple(token **lstHead) { CMD *cmd = mallocCMD(); while((*lstHead) && ((*lstHead)->type == SIMPLE || IS_RED((*lstHead)->type))) { cmd->type = SIMPLE; if((*lstHead)->type == SIMPLE) { //not a redirection cmd->argv[cmd->argc] = copyText((*lstHead)->text); cmd->argc++; cmd->argv = realloc(cmd->argv,(cmd->argc+1)*sizeof(char*)); cmd->argv[cmd->argc] = NULL; *lstHead = (*lstHead)->next; } else { //redirection found cmd = parseRedirect(lstHead,cmd); if(cmd->type == ERROR) { //if error occurred in parseRedirect return cmd; } } } if(cmd && cmd->type == NONE) { //case where no SIMPLE was found freeCMD(cmd); return NULL; } return cmd; }
static void aoff_link_free_block(Allctr_t *allctr, Block_t *block, Uint32 flags) { AOFFAllctr_t *alc = (AOFFAllctr_t *) allctr; AOFF_RBTree_t *blk = (AOFF_RBTree_t *) block; AOFF_RBTree_t **root = ((flags & ERTS_ALCU_FLG_SBMBC) ? &alc->sbmbc_root : &alc->mbc_root); Uint blk_sz = BLK_SZ(blk); #ifdef HARD_DEBUG check_tree(*root, 0); #endif blk->flags = 0; blk->left = NULL; blk->right = NULL; blk->max_sz = blk_sz; if (!*root) { blk->parent = NULL; SET_BLACK(blk); *root = blk; } else { AOFF_RBTree_t *x = *root; while (1) { if (x->max_sz < blk_sz) { x->max_sz = blk_sz; } if (blk < x) { if (!x->left) { blk->parent = x; x->left = blk; break; } x = x->left; } else { if (!x->right) { blk->parent = x; x->right = blk; break; } x = x->right; } } /* Insert block into size tree */ RBT_ASSERT(blk->parent); SET_RED(blk); if (IS_RED(blk->parent)) tree_insert_fixup(root, blk); } #ifdef HARD_DEBUG check_tree(*root, 0); #endif }
static void __traverse(node_t *n, int d, int _nrb) { int i; if ( n == NULL ) { if ( nrb == -1 ) nrb = _nrb; if ( nrb != _nrb ) printf("Imbalance at depth %d (%d,%d)\n", d, nrb, _nrb); return; } if ( IS_LEAF(n) && (n->k != 0) ) { assert(n->l == NULL); assert(n->r == NULL); assert(IS_BLACK(n->v)); } if ( !IS_LEAF(n) && IS_RED(n->v) ) { assert(IS_BLACK(n->l->v)); assert(IS_BLACK(n->r->v)); } if ( IS_BLACK(n->v) ) _nrb++; __traverse(n->l, d+1, _nrb); if ( valll > n->k ) bug=1; #if 0 for ( i = 0; i < d; i++ ) printf(" "); printf("%c%p K: %5d V: %p P: %p L: %p R: %p depth: %d\n", IS_BLACK(n->v) ? 'B' : 'R', n, n->k, n->v, n->p, n->l, n->r, d); #endif valll = n->k; __traverse(n->r, d+1, _nrb); }
static void aobf_link_free_block(Allctr_t *allctr, Block_t *block) { BFAllctr_t *bfallctr = (BFAllctr_t *) allctr; RBTree_t **root = &bfallctr->mbc_root; RBTree_t *blk = (RBTree_t *) block; Uint blk_sz = BF_BLK_SZ(blk); blk->flags = 0; blk->left = NULL; blk->right = NULL; if (!*root) { blk->parent = NULL; SET_BLACK(blk); *root = blk; } else { RBTree_t *x = *root; while (1) { Uint size; size = BF_BLK_SZ(x); if (blk_sz < size || (blk_sz == size && blk < x)) { if (!x->left) { blk->parent = x; x->left = blk; break; } x = x->left; } else { if (!x->right) { blk->parent = x; x->right = blk; break; } x = x->right; } } /* Insert block into size tree */ RBT_ASSERT(blk->parent); SET_RED(blk); if (IS_RED(blk->parent)) tree_insert_fixup(root, blk); } #ifdef HARD_DEBUG check_tree(root, 1, 0); #endif }
static void pn_unmove (struct pan_node *pn) { struct xq_move * move; GtkTreeIter iter[1]; gint nth; int id; GList *last; if (pn->move_count <= 0) { return; } pn->move_count --; move = pn->moves + pn->move_count; pn->cur_pan[move->fromy][move->fromx] = pn->cur_pan[move->toy][move->tox]; pn->cur_pan[move->toy][move->tox] = move->dead; if (move->dead) { memcpy (pn->cur_fen->pan, pn->cur_pan, 10 * 9 * sizeof (char)); pn->cur_fen->half_count = 0; pn->cur_fen->is_redturn = IS_BLACK (move->dead); pn->cur_moves = NULL; for (id = pn->move_count - 1, move = pn->moves + pn->move_count - 1; id >= 0 && move->dead == 0; id --, move = pn->moves + id) { pn->cur_fen->pan[move->fromy][move->fromx] = pn->cur_fen->pan[move->toy][move->tox]; pn->cur_fen->pan[move->toy][move->tox] = move->dead; pn->cur_moves = g_list_prepend (pn->cur_moves, move); pn->cur_fen->is_redturn = IS_RED (pn->cur_fen->pan[move->fromy][move->fromx]); pn->cur_fen->half_count ++; } } else { pn->cur_fen->half_count --; last = g_list_last (pn->cur_moves); pn->cur_moves = g_list_remove_link (pn->cur_moves, last); } nth = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (pn->qipu_list), NULL); gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (pn->qipu_list), iter, NULL, nth - 1); gtk_list_store_remove (GTK_LIST_STORE (pn->qipu_list), iter); }
static void pn_move (struct pan_node *xq, gint x, gint y, gint nx, gint ny) { GtkWidget *dia; char mes[0x100]; int isover; struct xq_move *move; GtkTreeIter iter[1]; GtkTreePath *path; GtkTreeView *tree; acc_debug ("move [%s] [%d:%d] -> [%d:%d]\n", zi_chinese[(int) xq->cur_pan[y][x]], x, y, nx, ny); if (xq->move_count >= sizeof (xq->moves) / sizeof (xq->moves[0])) { acc_err ( _("move count error.\n")); return; } move = xq->moves + xq->move_count; xq->move_count ++; move->dead = xq->cur_pan[ny][nx]; move->isred = IS_RED (xq->cur_pan[y][x]); move->fromx = x; move->fromy = y; move->tox = nx; move->toy = ny; move_to_desc (xq->cur_pan, move, mes, sizeof mes); gtk_list_store_append (GTK_LIST_STORE (xq->qipu_list), iter); gtk_list_store_set (GTK_LIST_STORE (xq->qipu_list), iter, 1, mes, -1); path = gtk_tree_model_get_path (GTK_TREE_MODEL (xq->qipu_list), iter); if (path) { tree = gtk_tree_selection_get_tree_view (GTK_TREE_SELECTION (xq->qipu_sel)); gtk_tree_view_scroll_to_cell (tree, path, NULL, FALSE, 0, 0); gtk_tree_path_free (path); } pan_move (xq->cur_pan, x, y, nx, ny); if (move->dead) { xq->cur_moves = NULL; memcpy (xq->cur_fen, xq->cur_pan, 10 * 9 * sizeof (char)); xq->cur_fen->half_count = 0; if (IS_RED (move->dead)) { xq->cur_fen->is_redturn = 1; } else { xq->cur_fen->is_redturn = 0; } } else { xq->cur_moves = g_list_append (xq->cur_moves, move); xq->cur_fen->half_count ++; } isover = zgxq_is_over (xq->cur_pan); if (isover) { xq->state = PAN_STATE_GAME_OVER; g_snprintf (mes, sizeof mes, _("!!!Game over. You %s.\n"), isover > 0 ? _("WIN") : _("LOSE")); dia = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, mes); gtk_dialog_run (GTK_DIALOG (dia)); gtk_widget_destroy (dia); g_signal_emit_by_name (xq->bstop, "clicked", xq); } }
static void bst_remove_repair(bst *t, bstnode *n) { bstnode *sib; /* case 1: n is root */ if (!n->parent) return; sib = SIBLING(n); /* case 2: n's sibling is red */ if (IS_RED(sib)) { n->parent->color = RED; sib->color = BLACK; if (IS_LEFT_CHILD(n)) bst_rotate_left(t, n->parent); else bst_rotate_right(t, n->parent); sib = SIBLING(n); } /* case 3: parent sib and sib's children are black */ if (n->parent->color == BLACK && sib->color == BLACK && IS_BLACK(sib->left) && IS_BLACK(sib->right)) { sib->color = RED; bst_remove_repair(t, n->parent); return; } /* case 4: parent is red, sib and sib's children are black */ if (n->parent->color == RED && sib->color == BLACK && IS_BLACK(sib->left) && IS_BLACK(sib->right)) { sib->color = RED; n->parent->color = BLACK; return; } /* case 5: a) n is left child, sib and sib->right child are black, sib->left is red b) n is right child, sib and sib->left child are black, sib->right is red */ if (IS_LEFT_CHILD(n) && sib->color == BLACK && IS_RED(sib->left) && IS_BLACK(sib->right)) { sib->color = RED; sib->left->color = BLACK; bst_rotate_right(t, sib); sib = SIBLING(n); } else if (IS_RIGHT_CHILD(n) && sib->color == BLACK && IS_RED(sib->right) && IS_BLACK(sib->left)) { sib->color = RED; sib->right->color = BLACK; bst_rotate_left(t, sib); sib = SIBLING(n); } /* case 6: */ sib->color = n->parent->color; n->parent->color = BLACK; if (IS_LEFT_CHILD(n)) { sib->right->color = BLACK; bst_rotate_left(t, n->parent); } else { sib->left->color = BLACK; bst_rotate_right(t, n->parent); } }
void map_insert(map_t *map, mapkey_t key, void *p) { allocator_t *alloc = map->allocator; mapnode_t *parent = map->root; mapnode_t **slot = &map->root; mapnode_t *insert; while (parent != NIL) { int comparison = map->ops.compare_key(key, parent->key); if (comparison == 0) { map->ops.destroy_value(parent->p, alloc); parent->p = map->ops.copy_value(p, alloc); return; } else if (comparison < 0) { if (parent->left != NIL) { parent = parent->left; continue; } else { slot = &parent->left; break; } } else { if (parent->right != NIL) { parent = parent->right; continue; } else { slot = &parent->right; break; } } } map->size += 1; insert = (mapnode_t *)com_malloc(map->allocator, sizeof(mapnode_t)); insert->left = insert->right = NIL; insert->key = map->ops.copy_key(key, alloc); insert->p = map->ops.copy_value(p, alloc); insert->color = RED; insert->parent = parent; *slot = insert; while (IS_RED(insert->parent) && node_grandparent(insert) != NIL) { mapnode_t *uncle = node_sibling(insert->parent); if (IS_RED(uncle)) { insert->parent->color = BLACK; uncle->color = BLACK; uncle->parent->color = RED; insert = uncle->parent; } else { int insleft = IS_LEFT(insert); int parleft = IS_LEFT(insert->parent); if (!insleft && parleft) { insert = insert->parent; node_rotate_left(map, insert); } else if (insleft && !parleft) { insert = insert->parent; node_rotate_right(map, insert); } insert->parent->parent->color = RED; insert->parent->color = BLACK; if (parleft) node_rotate_right(map, insert->parent->parent); else node_rotate_left(map, insert->parent->parent); } } map->root->color = BLACK; #if !defined(NDEBUG) map_test(map->root); #endif }
static void fix_unbalance_up(ptst_t *ptst, node_t *x) { qnode_t x_qn, g_qn, p_qn, w_qn, gg_qn; node_t *g, *p, *w, *gg; int done = 0; do { assert(IS_UNBALANCED(x->v)); if ( IS_GARBAGE(x) ) return; p = x->p; g = p->p; gg = g->p; mcs_lock(&gg->lock, &gg_qn); if ( !ADJACENT(gg, g) || IS_UNBALANCED(gg->v) || IS_GARBAGE(gg) ) goto unlock_gg; mcs_lock(&g->lock, &g_qn); if ( !ADJACENT(g, p) || IS_UNBALANCED(g->v) ) goto unlock_ggg; mcs_lock(&p->lock, &p_qn); if ( !ADJACENT(p, x) || IS_UNBALANCED(p->v) ) goto unlock_pggg; mcs_lock(&x->lock, &x_qn); assert(IS_RED(x->v)); assert(IS_UNBALANCED(x->v)); if ( IS_BLACK(p->v) ) { /* Case 1. Nothing to do. */ x->v = MK_BALANCED(x->v); done = 1; goto unlock_xpggg; } if ( IS_ROOT(x) ) { /* Case 2. */ x->v = MK_BLACK(MK_BALANCED(x->v)); done = 1; goto unlock_xpggg; } if ( IS_ROOT(p) ) { /* Case 2. */ p->v = MK_BLACK(p->v); x->v = MK_BALANCED(x->v); done = 1; goto unlock_xpggg; } if ( g->l == p ) w = g->r; else w = g->l; mcs_lock(&w->lock, &w_qn); if ( IS_RED(w->v) ) { /* Case 5. */ /* In all other cases, doesn't change colour or subtrees. */ if ( IS_UNBALANCED(w->v) ) goto unlock_wxpggg; g->v = MK_UNBALANCED(MK_RED(g->v)); p->v = MK_BLACK(p->v); w->v = MK_BLACK(w->v); x->v = MK_BALANCED(x->v); done = 2; goto unlock_wxpggg; } /* Cases 3 & 4. Both of these need the great-grandfather locked. */ if ( p == g->l ) { if ( x == p->l ) { /* Case 3. Single rotation. */ x->v = MK_BALANCED(x->v); p->v = MK_BLACK(p->v); g->v = MK_RED(g->v); right_rotate(ptst, g); } else { /* Case 4. Double rotation. */ x->v = MK_BALANCED(MK_BLACK(x->v)); g->v = MK_RED(g->v); left_rotate(ptst, p); right_rotate(ptst, g); } } else /* SYMMETRIC CASE */ { if ( x == p->r ) { /* Case 3. Single rotation. */ x->v = MK_BALANCED(x->v); p->v = MK_BLACK(p->v); g->v = MK_RED(g->v); left_rotate(ptst, g); } else { /* Case 4. Double rotation. */ x->v = MK_BALANCED(MK_BLACK(x->v)); g->v = MK_RED(g->v); right_rotate(ptst, p); left_rotate(ptst, g); } } done = 1; unlock_wxpggg: mcs_unlock(&w->lock, &w_qn); unlock_xpggg: mcs_unlock(&x->lock, &x_qn); unlock_pggg: mcs_unlock(&p->lock, &p_qn); unlock_ggg: mcs_unlock(&g->lock, &g_qn); unlock_gg: mcs_unlock(&gg->lock, &gg_qn); if ( done == 2 ) { x = g; done = 0; } } while ( !done ); }
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); } }
CMD *parseStage(token **lstHead) { CMD *cmd = parseSimple(lstHead); if(cmd && cmd->type == ERROR) { //propagate along an error return cmd; } /*if(*lstHead && (*lstHead)->type == PAR_RIGHT) { //right parenthesis before left...error! fprintf(stderr,"%s\n","Error: Right parenthesis before left"); return errorCMD(cmd); }*/ if(*lstHead && (*lstHead)->type == PAR_LEFT) { if(cmd) { //error..subcommand after command fprintf(stderr,"%s\n","Error: Subcommand after command"); return errorCMD(cmd); } *lstHead = (*lstHead)->next; cmd = mallocCMD(); if(*lstHead == NULL) { //error..invalid subcommand fprintf(stderr,"%s\n","Error: Invalid subcommand"); return errorCMD(cmd); } cmd->type = SUBCMD; cmd->left = parseCommand(lstHead); if(cmd->left->type == ERROR) { //propagate error return cmd->left; } if(*lstHead == NULL || ((*lstHead)->type != PAR_RIGHT && !IS_RED((*lstHead)->type))) { //error...parens incorrectly nested fprintf(stderr,"%s\n","Error: Incorrect parenthesis nesting"); return errorCMD(cmd); } *lstHead = (*lstHead)->next; if(*lstHead && IS_RED((*lstHead)->type)) { //redirection found cmd = parseRedirect(lstHead,cmd); if(cmd->type == ERROR) { //if error occurred in parseRedirect return cmd; } } } return cmd; }
void evaluate_last_move_snooker( struct Player * player, int * pact_player, BallsType * pballs, int * pqueue_view) { #define act_player (*pact_player) #define IS_RED(x) ( x==1 || x>=8 ) int red_balls_are_in_game=0; //static SnookerState st={SN_PLAY_RED}; int color_to_pot; int i; int act_score=0; int act_penalty=0; int foul=0; int ball_out; int other_player; int b1hit; char statusstr[200]; // make a better statusline #ifdef USE_SOUND int playsound = 0; // if set, play sound for new ball in only for one time for(i=0;i<22;i++) { pballs->ball[i].soundplayed = 0; } #endif emptyworkstring(); other_player=(act_player==1)?0:1; b1hit = BM_get_1st_ball_hit(); if(b1hit>=8) b1hit=1; if(player[act_player].place_cue_ball ) player[act_player].place_cue_ball=0; for(i=0;i<pballs->nr;i++) { if( IS_RED(pballs->ball[i].nr) && pballs->ball[i].in_game ) { red_balls_are_in_game=1; break; } } /* if white ball in */ if( BM_get_white_out() ) { foul=1; act_penalty =MAX(act_penalty,(BM_get_1st_ball_hit()<=7?BM_get_1st_ball_hit():4)); spot_snooker_ball(pballs,0); player[other_player].place_cue_ball=1; //Game ball lost concatworkstring(localeText[201]); #ifdef USE_SOUND if(options_gamemode==options_gamemode_tournament && player[0].is_AI && player[1].is_AI) { //nosound } else { PLAY_NOISE(wave_oneball,options_snd_volume); } #endif } switch(st.to_play) { case SN_PLAY_RED: color_to_pot=1; if(b1hit!=1) { foul=1; act_penalty=MAX(act_penalty,b1hit); } i=1; while((ball_out=BM_get_nth_ball_out(i++))>=0) { if(IS_RED(ball_out)) { act_score+=1; } else { act_penalty=MAX(act_penalty,ball_out); foul=1; #ifdef USE_SOUND playsound++; #endif } } for(i=2;i<8;i++) { // red out ? if( BM_get_ball_out(i)) { spot_snooker_ball(pballs,i); } } st.to_play=SN_PLAY_ANY_COLOR; if(foul) { //Red ball was required. concatworkstring(localeText[202]); } else { if(act_score>0) { //red ball - good concatworkstring(localeText[203]); } } break; case SN_PLAY_ANY_COLOR: if(b1hit==1) { foul=1; act_penalty=MAX(act_penalty,7); } color_to_pot=b1hit; i=1; while((ball_out=BM_get_nth_ball_out(i++))>=0) { if(ball_out==color_to_pot) { act_score+=ball_out; } else { foul=1; act_penalty=MAX(act_penalty,ball_out==1?7:ball_out); } #ifdef USE_SOUND playsound++; #endif } if(red_balls_are_in_game) { st.to_play=SN_PLAY_RED; } else { st.to_play=SN_PLAY_YELLOW; } for(i=2;i<8;i++) { if( BM_get_ball_out(i)) spot_snooker_ball(pballs,i); } if(foul) { //Colored ball was required. concatworkstring(localeText[204]); } else { if(act_score>0) { //Colored ball - good concatworkstring(localeText[205]); } } break; case SN_PLAY_YELLOW: case SN_PLAY_GREEN: case SN_PLAY_BROWN: case SN_PLAY_BLUE: case SN_PLAY_PINK: case SN_PLAY_BLACK: color_to_pot=st.to_play; if(b1hit!=color_to_pot) { foul=1; act_penalty=MAX(act_penalty,b1hit); act_penalty=MAX(act_penalty,color_to_pot); } i=1; while((ball_out=BM_get_nth_ball_out(i++))>=0) { if(ball_out==color_to_pot) { act_score+=ball_out; } else { foul=1; act_penalty=MAX(act_penalty,b1hit); act_penalty=MAX(act_penalty,color_to_pot); #ifdef USE_SOUND playsound++; #endif } } if(!foul && act_score>0) st.to_play++; for(i=st.to_play;i<8;i++) { if( BM_get_ball_out(i)) spot_snooker_ball(pballs,i); } if(foul) { //% s was required. sprintf(statusstr,localeText[206],localeText[st.to_play+177]); concatworkstring(statusstr); } else { if(act_score>0) { //% s holed - well done. sprintf(statusstr,localeText[207],localeText[st.to_play+176]); concatworkstring(statusstr); } } break; case SN_DONE: break; } if(foul) { act_penalty =MAX(act_penalty,4); player[other_player].score += act_penalty ; } else { player[act_player].score += act_score ; } if(act_score==0 || foul) { if(red_balls_are_in_game) { st.to_play=SN_PLAY_RED; } else { if(st.to_play<=SN_PLAY_ANY_COLOR) { st.to_play=SN_PLAY_YELLOW; } } player[act_player].queue_view=*pqueue_view; act_player = other_player; *pqueue_view=player[act_player].queue_view; if(strlen(player[act_player].name)>0) { //player %s court sprintf(statusstr,localeText[192],player[act_player].name); concatworkstring(statusstr); } else { //player %d court sprintf(statusstr,localeText[193],act_player+1); concatworkstring(statusstr); } } player[act_player].snooker_on_red=st.to_play==SN_PLAY_RED; player[act_player].snooker_next_color=st.to_play; if(st.to_play==SN_DONE) { other_player = (act_player+1)%2; if(player[act_player].score>player[other_player].score) { player[act_player].winner=1; player[other_player].winner=0; } if(player[act_player].score<player[other_player].score) { player[act_player].winner=0; player[other_player].winner=1; } // Change of snooker no end problem. Fix from Émeric Dupont if(player[act_player].score==player[other_player].score) { player[act_player].winner=1; player[other_player].winner=1; } // end change // game over, clear statusline emptyworkstring(); setst_text(); } #ifdef USE_SOUND if(playsound) { if(options_gamemode==options_gamemode_tournament && player[0].is_AI && player[1].is_AI) { //nosound } else { PLAY_NOISE(wave_oneball,options_snd_volume); } } #endif BM_reset_move_info(); setst_text(); }
/** * Balances red black trees. * @param t tree to balance. * @return balanced tree. */ static tree tree_fix(tree t) { if(IS_RED(t->left) && IS_RED(t->left->left)){ if(IS_RED(t->right)){ /*colour root red and children a,b black*/ t->colour = RED; t->left->colour = BLACK; t->right->colour = BLACK; }else if(IS_BLACK(t->right)){ /*right rotate root , colour new root (a) black, * and new child(old root) red*/ t = right_rotate(t); t->colour = BLACK; t->right->colour = RED;/*old root*/ } }else if(IS_RED(t->left) && IS_RED(t->left->right)){ if(IS_RED(t->right)){ /*colour root red and children a,b black*/ t->colour = RED; t->left->colour = BLACK; t->right->colour = BLACK; } else if(IS_BLACK(t->right)){ /* Left rotate left child (a), right rotate root (r), * colour new root (d) black and new child (R) red */ t->left = left_rotate(t->left); t = right_rotate(t); t->colour = BLACK; t->right->colour = RED;/* old root */ } }else if(IS_RED(t->right) && IS_RED(t->right->left)){ if(IS_RED(t->left)){ /* Colour root (R) red and children (a,b) black*/ t->colour = RED; t->left->colour = BLACK; t->right->colour = BLACK; }else if(IS_BLACK(t->left)){ /* Right rotate right child(b),left rotate root(r), * colour new root (e) black and new child (r) red */ t->right = right_rotate(t->right); t = left_rotate(t); t->colour = BLACK; t->left->colour = RED;/* old root */ } }else if(IS_RED(t->right) && IS_RED(t->right->right)){ if(IS_RED(t->left)){ /* Colour root (R) red and children (A,B) black */ t->colour = RED; t->left->colour = BLACK; t->right->colour = BLACK; } else if(IS_BLACK(t->left)){ /* Left rotate root R, colour new root b black and new child R red */ t = left_rotate(t); t->colour = BLACK; t->left->colour = RED;/*old root*/ } } return t; }
int rbt_remove(rbt_t *rbt, void *k, size_t klen, void **v) { rbt_node_t *node = _rbt_find_internal(rbt, rbt->root, k, klen); if (!node) return -1; if (node->left || node->right) { // the node is not a leaf // now check if it has two children or just one if (node->left && node->right) { // two children case rbt_node_t *n = NULL; static int prevnext = 0; int isprev = (prevnext++%2 == 0); if (isprev) n = rbt_find_prev(rbt, node); else n = rbt_find_next(rbt, node); node->key = realloc(node->key, n->klen); memcpy(node->key, n->key, n->klen); void *prev_value = node->value; node->value = n->value; if (isprev) { if (n == node->left) { node->left = n->left; } else { n->parent->right = n->left; } if (n->left) { n->left->parent = node; } } else { if (n == node->right) { node->right = n->right; } else { n->parent->left = n->right; } if (n->right) { n->right->parent = node; } } free(n->key); if (v) *v = prev_value; else if (rbt->free_value_cb) rbt->free_value_cb(prev_value); free(n); return 0; } else { // one child case rbt_node_t *child = node->right ? node->right : node->left; // replace node with child child->parent = node->parent; if (child->parent) { if (node == node->parent->left) node->parent->left = child; else node->parent->right = child; } if (IS_BLACK(node)) { if (IS_RED(child)) { PAINT_BLACK(child); } else { rbt_paint_onremove(rbt, child); } } if (v) *v = node->value; else if (rbt->free_value_cb) rbt->free_value_cb(node->value); free(node->key); free(node); return 0; } } // if it's not the root node we need to update the parent if (node->parent) { if (node == node->parent->left) node->parent->left = NULL; else node->parent->right = NULL; } if (v) *v = node->value; else if (rbt->free_value_cb && node->value) rbt->free_value_cb(node->value); free(node->key); free(node); return 0; }
void rbt_paint_onremove(rbt_t *rbt, rbt_node_t *node) { if (!node) return; // delete case 1 if (node->parent != NULL) { // delete case 2 rbt_node_t *sibling = rbt_sibling(node); if (IS_RED(sibling)) { PAINT_RED(node->parent); PAINT_BLACK(sibling); if (node == node->parent->left) { rbt_rotate_left(rbt, node->parent); } else { rbt_rotate_right(rbt, node->parent); } } // delete case 3 if (IS_BLACK(node->parent) && sibling && IS_BLACK(sibling) && IS_BLACK(sibling->left) && IS_BLACK(sibling->right)) { PAINT_RED(sibling); rbt_paint_onremove(rbt, node->parent); } else { // delete case 4 if (IS_RED(node->parent) && sibling && IS_BLACK(sibling) && IS_BLACK(sibling->left) && IS_BLACK(sibling->right)) { PAINT_RED(sibling); PAINT_BLACK(node->parent); } else { // delete case 5 if (IS_BLACK(sibling)) { if (node == node->parent->left && sibling && IS_BLACK(sibling->right) && IS_RED(sibling->left)) { PAINT_RED(sibling); PAINT_BLACK(sibling->left); rbt_rotate_right(rbt, sibling); } else if (node == node->parent->right && sibling && IS_BLACK(sibling->left) && IS_RED(sibling->right)) { PAINT_RED(sibling); PAINT_BLACK(sibling->right); rbt_rotate_left(rbt, sibling); } } // delete case 6 if (sibling) sibling->color = node->parent->color; PAINT_BLACK(node->parent); if (node == node->parent->left) { if (sibling) PAINT_BLACK(sibling->right); rbt_rotate_left(rbt, node->parent); } else { if (sibling) PAINT_BLACK(sibling->left); rbt_rotate_right(rbt, node->parent); } } } } }
int rbt_add(rbt_t *rbt, void *k, size_t klen, void *v) { int rc = 0; rbt_node_t *node = calloc(1, sizeof(rbt_node_t)); node->key = malloc(klen); memcpy(node->key, k, klen); node->klen = klen; node->value = v; if (!rbt->root) { PAINT_BLACK(node); rbt->root = node; } else { rc = _rbt_add_internal(rbt, rbt->root, node); if (IS_BLACK(node)) { // if the node just added is now black it means // it was already existing and this was only a value update if (!node->parent) { // we need to check also if the root pointer // should be updated as well rbt->root = node; } return 1; } if (!node->parent) { // case 1 PAINT_BLACK(node); rbt->root = node; } else if (IS_BLACK(node->parent)) { // case 2 return rc; } else { // case 3 rbt_node_t *uncle = rbt_uncle(node); rbt_node_t *grandparent = rbt_grandparent(node); if (IS_RED(uncle)) { PAINT_BLACK(node->parent); PAINT_BLACK(uncle); if (grandparent) { PAINT_RED(grandparent); rbt_add(rbt, grandparent->key, grandparent->klen, grandparent->value); } } else if (grandparent) { // case 4 if (node == node->parent->right && node->parent == grandparent->left) { rbt_rotate_left(rbt, node->parent); node = node->left; } else if (node == node->parent->left && node->parent == grandparent->right) { rbt_rotate_right(rbt, node->parent); node = node->right; } // case 5 grandparent = rbt_grandparent(node); if (node->parent) { PAINT_BLACK(node->parent); PAINT_RED(grandparent); if (node == node->parent->left) rbt_rotate_right(rbt, grandparent); else rbt_rotate_left(rbt, grandparent); } else { fprintf(stderr, "Corrupted tree\n"); return -1; } } } } return rc; }
void rb_delete_fixup(Node* &T, Node *x) { while ((NIL!= x) && !IS_ROOT(x) && IS_BLACK(x)) { if (IS_LEFT(x)) { // w是x的右兄弟,w是下面不同处理方式的选择依据 // 总共四种处理方式: // case 1: w是红色,两个孩子的颜色无所谓 // case 2: w是黑色,左孩子黑色,右孩子黑色 // case 3: w是黑色,左孩子红色,右孩子黑色 // case 4: w是黑色,右孩子红色,左孩子的颜色无所谓 Node *w = RIGHT(PARENT(x)); // case1: w是红色,则通过一次左旋,并刷成黑色,转成case 2、3、4 if (IS_RED(w)) { SET_BLACK(w); SET_RED(PARENT(x)); left_rotate(T, PARENT(x)); } // case 2: w的两个孩子都是黑色,把w刷成红色,x的父亲取代x,向上递归处理 if (IS_BLACK(LEFT(w)) && IS_BLACK(RIGHT(w))) { SET_RED(w); x = PARENT(x); continue; } // case 3: w的左孩子红色,右孩子黑色,把w左孩子刷成黑色,w刷成红色,做一次右旋,转成case 4 if (IS_BLACK(RIGHT(w))) { SET_BLACK(LEFT(w)); SET_RED(w); right_rotate(T, w); w = PARENT(w); // 转成case 4 } // case 4: w的右孩子为红色,把w刷成红色,w右节点刷成黑色,x父亲刷成黑色,做一次左旋,满足红黑性质,结束处理 COLOR(w) = COLOR(PARENT(x)); SET_BLACK(RIGHT(w)); SET_BLACK(PARENT(x)); left_rotate(T, PARENT(x)); x = T; } else { // w是x的左兄弟,w是下面不同处理方式的选择依据 // 总共四种处理方式: // case 1: w是红色,两个孩子的颜色无所谓 // case 2: w是黑色,左孩子黑色,右孩子黑色 // case 3: w是黑色,左孩子红色,右孩子黑色 // case 4: w是黑色,右孩子红色,左孩子的颜色无所谓 Node *w = LEFT(PARENT(x)); // case1: w是红色,则通过一次右旋,并刷成黑色,转成case 2、3、4 if (IS_RED(w)) { SET_BLACK(w); SET_RED(PARENT(x)); right_rotate(T, PARENT(x)); } // case 2: w的两个孩子都是黑色,把w刷成红色,x的父亲取代x,线上递归处理 if (IS_BLACK(LEFT(w)) && IS_BLACK(RIGHT(w))) { SET_RED(w); x = PARENT(x); continue; } // case 3: w的左孩子黑色,右孩子红色,把w右孩子刷成黑色,w刷成红色,做一次左旋,转成case 4 if (IS_BLACK(LEFT(w))) { SET_BLACK(RIGHT(w)); SET_RED(w); left_rotate(T, w); w = PARENT(w); // 转成case 4 } // case 4: w的左孩子为红色,把w刷成红色,w左节点刷成黑色,x父亲刷成黑色,做一次右旋,满足红黑性质,结束处理 COLOR(w) = COLOR(PARENT(x)); SET_BLACK(LEFT(w)); SET_BLACK(PARENT(x)); right_rotate(T, PARENT(x)); x = T; } } // 如果x是根节点,或为红色,则都刷成黑色,即可保持红黑树性质 SET_BLACK(x); }
static void fix_unbalance_down(ptst_t *ptst, node_t *x) { /* WN == W_NEAR, WF == W_FAR (W_FAR is further, in key space, from X). */ qnode_t x_qn, w_qn, p_qn, g_qn, wn_qn, wf_qn; node_t *w, *p, *g, *wn, *wf; int done = 0; do { if ( !IS_UNBALANCED(x->v) || IS_GARBAGE(x) ) return; p = x->p; g = p->p; mcs_lock(&g->lock, &g_qn); if ( !ADJACENT(g, p) || IS_UNBALANCED(g->v) || IS_GARBAGE(g) ) goto unlock_g; mcs_lock(&p->lock, &p_qn); if ( !ADJACENT(p, x) || IS_UNBALANCED(p->v) ) goto unlock_pg; mcs_lock(&x->lock, &x_qn); if ( !IS_BLACK(x->v) || !IS_UNBALANCED(x->v) ) { done = 1; goto unlock_xpg; } if ( IS_ROOT(x) ) { x->v = MK_BALANCED(x->v); done = 1; goto unlock_xpg; } w = (x == p->l) ? p->r : p->l; mcs_lock(&w->lock, &w_qn); if ( IS_UNBALANCED(w->v) ) { if ( IS_BLACK(w->v) ) { /* Funky relaxed rules to the rescue. */ x->v = MK_BALANCED(x->v); w->v = MK_BALANCED(w->v); if ( IS_BLACK(p->v) ) { p->v = MK_UNBALANCED(p->v); done = 2; } else { p->v = MK_BLACK(p->v); done = 1; } } goto unlock_wxpg; } assert(!IS_LEAF(w)); if ( x == p->l ) { wn = w->l; wf = w->r; } else { wn = w->r; wf = w->l; } mcs_lock(&wn->lock, &wn_qn); /* Hanke has an extra relaxed transform here. It's not needed. */ if ( IS_UNBALANCED(wn->v) ) goto unlock_wnwxpg; mcs_lock(&wf->lock, &wf_qn); if ( IS_UNBALANCED(wf->v) ) goto unlock_wfwnwxpg; if ( IS_RED(w->v) ) { /* Case 1. Rotate at parent. */ assert(IS_BLACK(p->v) && IS_BLACK(wn->v) && IS_BLACK(wf->v)); w->v = MK_BLACK(w->v); p->v = MK_RED(p->v); if ( x == p->l ) left_rotate(ptst, p); else right_rotate(ptst, p); goto unlock_wfwnwxpg; } if ( IS_BLACK(wn->v) && IS_BLACK(wf->v) ) { if ( IS_RED(p->v) ) { /* Case 2. Simple recolouring. */ p->v = MK_BLACK(p->v); done = 1; } else { /* Case 5. Simple recolouring. */ p->v = MK_UNBALANCED(p->v); done = 2; } w->v = MK_RED(w->v); x->v = MK_BALANCED(x->v); goto unlock_wfwnwxpg; } if ( x == p->l ) { if ( IS_RED(wf->v) ) { /* Case 3. Single rotation. */ wf->v = MK_BLACK(wf->v); w->v = SET_COLOUR(w->v, GET_COLOUR(p->v)); p->v = MK_BLACK(p->v); x->v = MK_BALANCED(x->v); left_rotate(ptst, p); } else { /* Case 4. Double rotation. */ assert(IS_RED(wn->v)); wn->v = SET_COLOUR(wn->v, GET_COLOUR(p->v)); p->v = MK_BLACK(p->v); x->v = MK_BALANCED(x->v); right_rotate(ptst, w); left_rotate(ptst, p); } } else /* SYMMETRIC CASE: X == P->R */ { if ( IS_RED(wf->v) ) { /* Case 3. Single rotation. */ wf->v = MK_BLACK(wf->v); w->v = SET_COLOUR(w->v, GET_COLOUR(p->v)); p->v = MK_BLACK(p->v); x->v = MK_BALANCED(x->v); right_rotate(ptst, p); } else { /* Case 4. Double rotation. */ assert(IS_RED(wn->v)); wn->v = SET_COLOUR(wn->v, GET_COLOUR(p->v)); p->v = MK_BLACK(p->v); x->v = MK_BALANCED(x->v); left_rotate(ptst, w); right_rotate(ptst, p); } } done = 1; unlock_wfwnwxpg: mcs_unlock(&wf->lock, &wf_qn); unlock_wnwxpg: mcs_unlock(&wn->lock, &wn_qn); unlock_wxpg: mcs_unlock(&w->lock, &w_qn); unlock_xpg: mcs_unlock(&x->lock, &x_qn); unlock_pg: mcs_unlock(&p->lock, &p_qn); unlock_g: mcs_unlock(&g->lock, &g_qn); if ( done == 2 ) { x = p; done = 0; } } while ( !done ); }
static rbt rbt_fix(rbt r) { if(IS_RED(r->left) && IS_RED(r->left->left)){ if(IS_RED(r->right)){ /*colour root red and children a,b black*/ r->colour = RED; r->left->colour = BLACK; r->right->colour = BLACK; }else if(IS_BLACK(r->right)){ /*right rotate root , colour new root (a) black, and new child(old root) red*/ r = right_rotate(r); r->colour = BLACK; r->right->colour = RED;/*old root?*/ } }else if(IS_RED(r->left) && IS_RED(r->left->right)){ if(IS_RED(r->right)){ /*colour root red and children a,b black*/ r->colour = RED; r->left->colour = BLACK; r->right->colour = BLACK; } else if(IS_BLACK(r->right)){ /*left rotate left child (a), right rotate root (r),colour new root (d) black and new child (R) red*/ r->left = left_rotate(r->left); r = right_rotate(r); r->colour = BLACK; r->right->colour = RED;/*old root?*/ } }else if(IS_RED(r->right) && IS_RED(r->right->left)){ if(IS_RED(r->left)){ /* colour root (R) red and children (a,b) black*/ r->colour = RED; r->left->colour = BLACK; r->right->colour = BLACK; }else if(IS_BLACK(r->left)){ /*right rotate right child(b),left rotate root(r),colour new root (e) black and new child (r) red*/ r->right = right_rotate(r->right); r = left_rotate(r); r->colour = BLACK; r->left->colour = RED;/*old root?*/ } }else if(IS_RED(r->right) && IS_RED(r->right->right)){ if(IS_RED(r->left)){ /*colour root (R) red and children (A,B) black*/ r->colour = RED; r->left->colour = BLACK; r->right->colour = BLACK; } else if(IS_BLACK(r->left)){ /*left rotate root R, colour new root b black and new child R red*/ r = left_rotate(r); r->colour = BLACK; r->left->colour = RED;/*old root?*/ } } return r; }
static void tree_insert_fixup(RBTree_t **root, RBTree_t *blk) { RBTree_t *x = blk, *y; /* * Rearrange the tree so that it satisfies the Red-Black Tree properties */ RBT_ASSERT(x != *root && IS_RED(x->parent)); do { /* * x and its parent are both red. Move the red pair up the tree * until we get to the root or until we can separate them. */ RBT_ASSERT(IS_RED(x)); RBT_ASSERT(IS_BLACK(x->parent->parent)); RBT_ASSERT(x->parent->parent); if (x->parent == x->parent->parent->left) { y = x->parent->parent->right; if (IS_RED(y)) { SET_BLACK(y); x = x->parent; SET_BLACK(x); x = x->parent; SET_RED(x); } else { if (x == x->parent->right) { x = x->parent; left_rotate(root, x); } RBT_ASSERT(x == x->parent->parent->left->left); RBT_ASSERT(IS_RED(x)); RBT_ASSERT(IS_RED(x->parent)); RBT_ASSERT(IS_BLACK(x->parent->parent)); RBT_ASSERT(IS_BLACK(y)); SET_BLACK(x->parent); SET_RED(x->parent->parent); right_rotate(root, x->parent->parent); RBT_ASSERT(x == x->parent->left); RBT_ASSERT(IS_RED(x)); RBT_ASSERT(IS_RED(x->parent->right)); RBT_ASSERT(IS_BLACK(x->parent)); break; } } else { RBT_ASSERT(x->parent == x->parent->parent->right); y = x->parent->parent->left; if (IS_RED(y)) { SET_BLACK(y); x = x->parent; SET_BLACK(x); x = x->parent; SET_RED(x); } else { if (x == x->parent->left) { x = x->parent; right_rotate(root, x); } RBT_ASSERT(x == x->parent->parent->right->right); RBT_ASSERT(IS_RED(x)); RBT_ASSERT(IS_RED(x->parent)); RBT_ASSERT(IS_BLACK(x->parent->parent)); RBT_ASSERT(IS_BLACK(y)); SET_BLACK(x->parent); SET_RED(x->parent->parent); left_rotate(root, x->parent->parent); RBT_ASSERT(x == x->parent->right); RBT_ASSERT(IS_RED(x)); RBT_ASSERT(IS_RED(x->parent->left)); RBT_ASSERT(IS_BLACK(x->parent)); break; } } } while (x != *root && IS_RED(x->parent)); SET_BLACK(*root); }
static AOFF_RBTree_t * check_tree(Carrier_t* within_crr, enum AOFFSortOrder order, AOFF_RBTree_t* root, Uint size) { AOFF_RBTree_t *res = NULL; Sint blacks; Sint curr_blacks; AOFF_RBTree_t *x; Carrier_t* crr; Uint depth, max_depth, node_cnt; #ifdef PRINT_TREE print_tree(root); #endif ASSERT((within_crr && order >= FF_AOFF) || (!within_crr && order <= FF_AOFF)); if (!root) return res; x = root; ASSERT(IS_BLACK(x)); ASSERT(!x->parent); curr_blacks = 1; blacks = -1; depth = 1; max_depth = 0; node_cnt = 0; while (x) { if (!IS_LEFT_VISITED(x)) { SET_LEFT_VISITED(x); if (x->left) { x = x->left; ++depth; if (IS_BLACK(x)) curr_blacks++; continue; } else { if (blacks < 0) blacks = curr_blacks; ASSERT(blacks == curr_blacks); } } if (!IS_RIGHT_VISITED(x)) { SET_RIGHT_VISITED(x); if (x->right) { x = x->right; ++depth; if (IS_BLACK(x)) curr_blacks++; continue; } else { if (blacks < 0) blacks = curr_blacks; ASSERT(blacks == curr_blacks); } } ++node_cnt; if (depth > max_depth) max_depth = depth; if (within_crr) { crr = FBLK_TO_MBC(&x->hdr); ASSERT(crr == within_crr); ASSERT((char*)x > (char*)crr); ASSERT(((char*)x + AOFF_BLK_SZ(x)) <= ((char*)crr + CARRIER_SZ(crr))); } if (order == FF_BF) { AOFF_RBTree_t* y = x; AOFF_RBTree_t* nxt = LIST_NEXT(y); ASSERT(IS_TREE_NODE(x)); while (nxt) { ASSERT(IS_LIST_ELEM(nxt)); ASSERT(AOFF_BLK_SZ(nxt) == AOFF_BLK_SZ(x)); ASSERT(FBLK_TO_MBC(&nxt->hdr) == within_crr); ASSERT(LIST_PREV(nxt) == y); y = nxt; nxt = LIST_NEXT(nxt); } } if (IS_RED(x)) { ASSERT(IS_BLACK(x->right)); ASSERT(IS_BLACK(x->left)); } ASSERT(x->parent || x == root); if (x->left) { ASSERT(x->left->parent == x); ASSERT(cmp_blocks(order, x->left, x) < 0); ASSERT(x->left->max_sz <= x->max_sz); } if (x->right) { ASSERT(x->right->parent == x); ASSERT(cmp_blocks(order, x->right, x) > 0); ASSERT(x->right->max_sz <= x->max_sz); } ASSERT(x->max_sz >= AOFF_BLK_SZ(x)); ASSERT(x->max_sz == AOFF_BLK_SZ(x) || x->max_sz == (x->left ? x->left->max_sz : 0) || x->max_sz == (x->right ? x->right->max_sz : 0)); if (size && AOFF_BLK_SZ(x) >= size) { if (!res || cmp_blocks(order, x, res) < 0) { res = x; } } UNSET_LEFT_VISITED(x); UNSET_RIGHT_VISITED(x); if (IS_BLACK(x)) curr_blacks--; x = x->parent; --depth; } ASSERT(depth == 0 || (!root && depth==1)); ASSERT(curr_blacks == 0); ASSERT((1 << (max_depth/2)) <= node_cnt); UNSET_LEFT_VISITED(root); UNSET_RIGHT_VISITED(root); return res; }
setval_t set_update(set_t *s, setkey_t k, setval_t v, int overwrite) { ptst_t *ptst; qnode_t y_qn, z_qn; node_t *y, *z, *new_internal, *new_leaf; int fix_up = 0; setval_t ov = NULL; k = CALLER_TO_INTERNAL_KEY(k); ptst = critical_enter(); retry: z = &s->root; while ( (y = (k <= z->k) ? z->l : z->r) != NULL ) z = y; y = z->p; mcs_lock(&y->lock, &y_qn); if ( (((k <= y->k) ? y->l : y->r) != z) || IS_GARBAGE(y) ) { mcs_unlock(&y->lock, &y_qn); goto retry; } mcs_lock(&z->lock, &z_qn); assert(!IS_GARBAGE(z) && IS_LEAF(z)); if ( z->k == k ) { ov = GET_VALUE(z->v); if ( overwrite || (ov == NULL) ) SET_VALUE(z->v, v); } else { new_leaf = gc_alloc(ptst, gc_id); new_internal = gc_alloc(ptst, gc_id); new_leaf->k = k; new_leaf->v = MK_BLACK(v); new_leaf->l = NULL; new_leaf->r = NULL; new_leaf->p = new_internal; mcs_init(&new_leaf->lock); if ( z->k < k ) { new_internal->k = z->k; new_internal->l = z; new_internal->r = new_leaf; } else { new_internal->k = k; new_internal->l = new_leaf; new_internal->r = z; } new_internal->p = y; mcs_init(&new_internal->lock); if ( IS_UNBALANCED(z->v) ) { z->v = MK_BALANCED(z->v); new_internal->v = MK_BLACK(INTERNAL_VALUE); } else if ( IS_RED(y->v) ) { new_internal->v = MK_UNBALANCED(MK_RED(INTERNAL_VALUE)); fix_up = 1; } else { new_internal->v = MK_RED(INTERNAL_VALUE); } WMB(); z->p = new_internal; if ( y->l == z ) y->l = new_internal; else y->r = new_internal; } mcs_unlock(&y->lock, &y_qn); mcs_unlock(&z->lock, &z_qn); if ( fix_up ) fix_unbalance_up(ptst, new_internal); out: critical_exit(ptst); return ov; }
static RBTree_t * check_tree(RBTree_t *root, int ao, Uint size) { RBTree_t *res = NULL; Sint blacks; Sint curr_blacks; RBTree_t *x; #ifdef PRINT_TREE print_tree(root, ao); #endif if (!root) return res; x = root; ASSERT(IS_BLACK(x)); ASSERT(!x->parent); curr_blacks = 1; blacks = -1; while (x) { if (!IS_LEFT_VISITED(x)) { SET_LEFT_VISITED(x); if (x->left) { x = x->left; if (IS_BLACK(x)) curr_blacks++; continue; } else { if (blacks < 0) blacks = curr_blacks; ASSERT(blacks == curr_blacks); } } if (!IS_RIGHT_VISITED(x)) { SET_RIGHT_VISITED(x); if (x->right) { x = x->right; if (IS_BLACK(x)) curr_blacks++; continue; } else { if (blacks < 0) blacks = curr_blacks; ASSERT(blacks == curr_blacks); } } if (IS_RED(x)) { ASSERT(IS_BLACK(x->right)); ASSERT(IS_BLACK(x->left)); } ASSERT(x->parent || x == root); if (x->left) { ASSERT(x->left->parent == x); if (ao) { ASSERT(BF_BLK_SZ(x->left) < BF_BLK_SZ(x) || (BF_BLK_SZ(x->left) == BF_BLK_SZ(x) && x->left < x)); } else { ASSERT(IS_TREE_NODE(x->left)); ASSERT(BF_BLK_SZ(x->left) < BF_BLK_SZ(x)); } } if (x->right) { ASSERT(x->right->parent == x); if (ao) { ASSERT(BF_BLK_SZ(x->right) > BF_BLK_SZ(x) || (BF_BLK_SZ(x->right) == BF_BLK_SZ(x) && x->right > x)); } else { ASSERT(IS_TREE_NODE(x->right)); ASSERT(BF_BLK_SZ(x->right) > BF_BLK_SZ(x)); } } if (size && BF_BLK_SZ(x) >= size) { if (ao) { if (!res || BF_BLK_SZ(x) < BF_BLK_SZ(res) || (BF_BLK_SZ(x) == BF_BLK_SZ(res) && x < res)) res = x; } else { if (!res || BF_BLK_SZ(x) < BF_BLK_SZ(res)) res = x; } } UNSET_LEFT_VISITED(x); UNSET_RIGHT_VISITED(x); if (IS_BLACK(x)) curr_blacks--; x = x->parent; } ASSERT(curr_blacks == 0); UNSET_LEFT_VISITED(root); UNSET_RIGHT_VISITED(root); return res; }
static void rbt_delete(AOFF_RBTree_t** root, AOFF_RBTree_t* del) { Uint spliced_is_black; AOFF_RBTree_t *x, *y, *z = del; AOFF_RBTree_t null_x; /* null_x is used to get the fixup started when we splice out a node without children. */ HARD_CHECK_IS_MEMBER(*root, del); null_x.parent = NULL; /* Remove node from tree... */ /* Find node to splice out */ if (!z->left || !z->right) y = z; else /* Set y to z:s successor */ for(y = z->right; y->left; y = y->left); /* splice out y */ x = y->left ? y->left : y->right; spliced_is_black = IS_BLACK(y); if (x) { x->parent = y->parent; } else if (spliced_is_black) { x = &null_x; x->flags = 0; SET_BLACK(x); x->right = x->left = NULL; x->max_sz = 0; x->parent = y->parent; y->left = x; } if (!y->parent) { RBT_ASSERT(*root == y); *root = x; } else { if (y == y->parent->left) { y->parent->left = x; } else { RBT_ASSERT(y == y->parent->right); y->parent->right = x; } if (y->parent != z) { lower_max_size(y->parent, (y==z ? NULL : z)); } } if (y != z) { /* We spliced out the successor of z; replace z by the successor */ ASSERT(z != &null_x); replace(root, z, y); lower_max_size(y, NULL); } if (spliced_is_black) { /* We removed a black node which makes the resulting tree violate the Red-Black Tree properties. Fixup tree... */ while (IS_BLACK(x) && x->parent) { /* * x has an "extra black" which we move up the tree * until we reach the root or until we can get rid of it. * * y is the sibbling of x */ if (x == x->parent->left) { y = x->parent->right; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); left_rotate(root, x->parent); y = x->parent->right; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->left) && IS_BLACK(y->right)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->right)) { SET_BLACK(y->left); SET_RED(y); right_rotate(root, y); y = x->parent->right; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->right); SET_BLACK(y->right); left_rotate(root, x->parent); x = *root; break; } } else { RBT_ASSERT(x == x->parent->right); y = x->parent->left; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); right_rotate(root, x->parent); y = x->parent->left; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->right) && IS_BLACK(y->left)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->left)) { SET_BLACK(y->right); SET_RED(y); left_rotate(root, y); y = x->parent->left; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->left); SET_BLACK(y->left); right_rotate(root, x->parent); x = *root; break; } } } SET_BLACK(x); if (null_x.parent) { if (null_x.parent->left == &null_x) null_x.parent->left = NULL; else { RBT_ASSERT(null_x.parent->right == &null_x); null_x.parent->right = NULL; } RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } else if (*root == &null_x) { *root = NULL; RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } } }
/* * The argument types of "Allctr_t *" and "Block_t *" have been * chosen since we then can use tree_delete() as unlink_free_block * callback function in the address order case. */ static void tree_delete(Allctr_t *allctr, Block_t *del) { BFAllctr_t *bfallctr = (BFAllctr_t *) allctr; Uint spliced_is_black; RBTree_t **root = &bfallctr->mbc_root; RBTree_t *x, *y, *z = (RBTree_t *) del; RBTree_t null_x; /* null_x is used to get the fixup started when we splice out a node without children. */ null_x.parent = NULL; #ifdef HARD_DEBUG check_tree(*root, bfallctr->address_order, 0); #endif /* Remove node from tree... */ /* Find node to splice out */ if (!z->left || !z->right) y = z; else /* Set y to z:s successor */ for(y = z->right; y->left; y = y->left); /* splice out y */ x = y->left ? y->left : y->right; spliced_is_black = IS_BLACK(y); if (x) { x->parent = y->parent; } else if (!x && spliced_is_black) { x = &null_x; x->flags = 0; SET_BLACK(x); x->right = x->left = NULL; x->parent = y->parent; y->left = x; } if (!y->parent) { RBT_ASSERT(*root == y); *root = x; } else if (y == y->parent->left) y->parent->left = x; else { RBT_ASSERT(y == y->parent->right); y->parent->right = x; } if (y != z) { /* We spliced out the successor of z; replace z by the successor */ replace(root, z, y); } if (spliced_is_black) { /* We removed a black node which makes the resulting tree violate the Red-Black Tree properties. Fixup tree... */ while (IS_BLACK(x) && x->parent) { /* * x has an "extra black" which we move up the tree * until we reach the root or until we can get rid of it. * * y is the sibbling of x */ if (x == x->parent->left) { y = x->parent->right; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); left_rotate(root, x->parent); y = x->parent->right; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->left) && IS_BLACK(y->right)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->right)) { SET_BLACK(y->left); SET_RED(y); right_rotate(root, y); y = x->parent->right; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->right); SET_BLACK(y->right); left_rotate(root, x->parent); x = *root; break; } } else { RBT_ASSERT(x == x->parent->right); y = x->parent->left; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); right_rotate(root, x->parent); y = x->parent->left; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->right) && IS_BLACK(y->left)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->left)) { SET_BLACK(y->right); SET_RED(y); left_rotate(root, y); y = x->parent->left; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->left); SET_BLACK(y->left); right_rotate(root, x->parent); x = *root; break; } } } SET_BLACK(x); if (null_x.parent) { if (null_x.parent->left == &null_x) null_x.parent->left = NULL; else { RBT_ASSERT(null_x.parent->right == &null_x); null_x.parent->right = NULL; } RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } else if (*root == &null_x) { *root = NULL; RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } } DESTROY_TREE_NODE(del); #ifdef HARD_DEBUG check_tree(root, bfallctr->address_order, 0); #endif }
static void rbt_insert(enum AOFFSortOrder order, AOFF_RBTree_t** root, AOFF_RBTree_t* blk) { Uint blk_sz = AOFF_BLK_SZ(blk); #ifdef DEBUG blk->flags = (order == FF_BF) ? IS_BF_FLG : 0; #else blk->flags = 0; #endif blk->left = NULL; blk->right = NULL; blk->max_sz = blk_sz; if (!*root) { blk->parent = NULL; SET_BLACK(blk); *root = blk; } else { AOFF_RBTree_t *x = *root; while (1) { SWord diff; if (x->max_sz < blk_sz) { x->max_sz = blk_sz; } diff = cmp_blocks(order, blk, x); if (diff < 0) { if (!x->left) { blk->parent = x; x->left = blk; break; } x = x->left; } else if (diff > 0) { if (!x->right) { blk->parent = x; x->right = blk; break; } x = x->right; } else { ASSERT(order == FF_BF); ASSERT(blk->flags & IS_BF_FLG); ASSERT(x->flags & IS_BF_FLG); SET_LIST_ELEM(blk); LIST_NEXT(blk) = LIST_NEXT(x); LIST_PREV(blk) = x; if (LIST_NEXT(x)) LIST_PREV(LIST_NEXT(x)) = blk; LIST_NEXT(x) = blk; return; } } /* Insert block into size tree */ RBT_ASSERT(blk->parent); SET_RED(blk); if (IS_RED(blk->parent)) tree_insert_fixup(root, blk); } if (order == FF_BF) { SET_TREE_NODE(blk); LIST_NEXT(blk) = NULL; } }
static void bf_link_free_block(Allctr_t *allctr, Block_t *block) { BFAllctr_t *bfallctr = (BFAllctr_t *) allctr; RBTree_t **root = &bfallctr->mbc_root; RBTree_t *blk = (RBTree_t *) block; Uint blk_sz = BF_BLK_SZ(blk); SET_TREE_NODE(blk); blk->flags = 0; blk->left = NULL; blk->right = NULL; if (!*root) { blk->parent = NULL; SET_BLACK(blk); *root = blk; } else { RBTree_t *x = *root; while (1) { Uint size; size = BF_BLK_SZ(x); if (blk_sz == size) { SET_LIST_ELEM(blk); LIST_NEXT(blk) = LIST_NEXT(x); LIST_PREV(blk) = x; if (LIST_NEXT(x)) LIST_PREV(LIST_NEXT(x)) = blk; LIST_NEXT(x) = blk; return; /* Finnished */ } else if (blk_sz < size) { if (!x->left) { blk->parent = x; x->left = blk; break; } x = x->left; } else { if (!x->right) { blk->parent = x; x->right = blk; break; } x = x->right; } } RBT_ASSERT(blk->parent); SET_RED(blk); if (IS_RED(blk->parent)) tree_insert_fixup(root, blk); } SET_TREE_NODE(blk); LIST_NEXT(blk) = NULL; #ifdef HARD_DEBUG check_tree(root, 0, 0); #endif }
static void mapnode_remove(map_t *map, mapnode_t *node) { allocator_t *alloc = map->allocator; mapnode_t *destroyed, *y, *z; if (node->left == NIL) { destroyed = node; y = node->right; } else if (node->right == NIL) { destroyed = node; y = node->left; } else { destroyed = node->left; while (destroyed->right != NIL) destroyed = destroyed->right; y = destroyed->left; node->key = destroyed->key; node->p = destroyed->p; } z = destroyed->parent; if (y != NIL) y->parent = z; if (z == NIL) { map->root = y; goto finish_removal; } if (destroyed == z->left) { z->left = y; } else { z->right = y; } if (IS_BLACK(destroyed)) { while (y != map->root && IS_BLACK(y)) { mapnode_t *sibling; int dir = !(y == z->left); sibling = OPP_NODE(z, dir); if (IS_RED(sibling)) { sibling->color = BLACK; z->color = RED; g_rotations[dir](map, z); sibling = OPP_NODE(z, dir); } if (IS_BLACK(sibling->left) && IS_BLACK(sibling->right)) { sibling->color = RED; y = z; z = z->parent; } else { if (IS_BLACK(OPP_NODE(sibling, dir))) { DIR_NODE(sibling, dir)->color = BLACK; sibling->color = RED; g_rotations[!dir](map, sibling); sibling = OPP_NODE(z, dir); } sibling->color = z->color; z->color = BLACK; OPP_NODE(sibling, dir)->color = BLACK; g_rotations[dir](map, z); y = map->root; } } y->color = BLACK; } finish_removal: com_free(alloc, destroyed); map->size -= 1; #if !defined(NDEBUG) map_test(map->root); #endif }