示例#1
0
文件: map.c 项目: nilium/snow-palm
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;
}
示例#2
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);
}
示例#3
0
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
}
示例#5
0
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);
}
示例#6
0
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
}
示例#7
0
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);
}
示例#8
0
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);
    }
}
示例#9
0
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);
    }
}
示例#10
0
文件: map.c 项目: nilium/snow-palm
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
}
示例#11
0
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 );
}
示例#12
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);
    }
}
示例#13
0
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;
}
示例#14
0
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();
}
示例#15
0
文件: tree.c 项目: lchish/cosc
/**
 * 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;
}
示例#16
0
文件: rbtree.c 项目: cloud-hot/libhl
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;
}
示例#17
0
文件: rbtree.c 项目: cloud-hot/libhl
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);
                }
            }
        }
    }
}
示例#18
0
文件: rbtree.c 项目: cloud-hot/libhl
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;
}
示例#19
0
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);
}
示例#20
0
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 );
}
示例#21
0
文件: rbt.c 项目: lchish/cosc
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;
}
示例#22
0
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;

}
示例#24
0
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;
}
示例#25
0
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);
	}
    }
}
示例#27
0
/*
 * 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;
    }
}
示例#29
0
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
}
示例#30
0
文件: map.c 项目: nilium/snow-palm
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
}