Esempio n. 1
0
void * insertelt_rbtree_sub ( RBTREE tree, RBNODE node, int (*compfun)(const void *,const void *), void * key, void * value){
	assert(NULL!=node);
	assert(NULL!=compfun);
	assert(NULL!=key);
	assert(NULL!=value);

	int comparison = compfun(key,node->key);
	if ( comparison == 0){
		/*  key already in tree. Balancing not affected */
		void * oldvalue = node->value;
		node->value = value;
		return oldvalue;
	}

	RBNODE * childnodep = NULL;
	if ( comparison<0 ){
		childnodep = &(node->left);
	} else if ( comparison>0 ){
		childnodep = &(node->right);
	}

	/*  Continue down tree */	
	if (NULL != *childnodep){return insertelt_rbtree_sub(tree,*childnodep,compfun,key,value);}

	*childnodep = create_rbnode(red);
	(*childnodep)->key = tree->copykey(key);
	(*childnodep)->value = value;
	(*childnodep)->parent = node;
	balance_rbtree (*childnodep,tree);
	return NULL;
}
Esempio n. 2
0
void rb_insert(rbtree* tree, int data) {
    rbnode* pn = rb_search(tree, data);
    rbnode* nn = create_rbnode(data);
    if (!pn) {
        tree->root = nn;
        nn->color = BLACK;
        return;
    }
    else if (data == pn->data) {
        return;
    }
    else if (data < pn->data) {
        pn->left = nn;
        nn->parent = pn;
    }
    else if (data > pn->data) {
        pn->right = nn;
        nn->parent = pn;
    }
    while (pn && pn->color == RED) {
        if (IS_LEFT(pn)) {
            rbnode* uncle = pn->parent->right;
            if (uncle && uncle->color == RED) {
                pn->color = uncle->color = BLACK;
                pn->parent->color = RED;
                nn = pn->parent;
                pn = nn->parent;
                continue;
            }
            if (IS_RIGHT(nn)) {
                LEFT_ROTATE(tree, pn);
                SWAP(nn, pn, rbnode*);
            }
            RIGHT_ROTATE(tree, pn->parent);
            pn->color = BLACK;
            pn->right->color = RED;
            break;
        }
        else {
            rbnode* uncle = pn->parent->left;
            if (uncle && uncle->color == RED) {
                pn->color = uncle->color = BLACK;
                pn->parent->color = RED;
                nn = pn->parent;
                pn = nn->parent;
                continue;
            }
            if (IS_LEFT(nn)) {
                RIGHT_ROTATE(tree, pn);
                SWAP(nn, pn, rbnode*);
            }
            LEFT_ROTATE(tree, pn->parent);
            pn->color = BLACK;
            pn->left->color = RED;
            break;
        }
    }
    // nn is root
    if (!pn) nn->color = BLACK;
}
Esempio n. 3
0
void * insertelt_rbtree ( RBTREE tree, void * key, void * value){
	assert(NULL!=tree);
	assert(NULL!=key);
	assert(NULL!=value);
	if ( NULL==tree->root){
		/*  Tree empty, root must be black */
		tree->root = create_rbnode (black);
		tree->root->key = tree->copykey(key);
		tree->root->value = value;
		tree->root->parent = NULL;
		return NULL;
	}

	/*  Find location to add  */
	return insertelt_rbtree_sub (tree, tree->root, tree->compfun, key, value);
}
Esempio n. 4
0
RBNODE copy_rbnode_sub ( const RBNODE node, void * (*copykey)(const void *), void * (*copyvalue)(const void *) ){
	assert(NULL!=node);
	assert(NULL!=copykey);

	RBNODE newnode = create_rbnode(black);
	newnode->colour = node->colour;
	newnode->key = copykey(node->key);
	newnode->value = (NULL!=copyvalue)?copyvalue(node->value):node->value;
	if (NULL!=node->left){
		newnode->left = copy_rbnode_sub(node->left,copykey,copyvalue);
		newnode->left->parent = newnode;
	}
	if (NULL!=node->right){
		newnode->right = copy_rbnode_sub(node->right,copykey,copyvalue);
		newnode->right->parent = newnode;
	}
	return newnode;
}
Esempio n. 5
0
/*  Need to decide what to do about memory for keys.
 * Possible memory leak at moment.  */
void * removeelt_rbtree (RBTREE tree, const void * key){
	RBNODE phantom = NULL;
	void * retval = NULL;
	assert(NULL!=tree);
	assert(NULL!=key);

	RBNODE delnode = search_rbtree(tree,key);
	if (NULL==delnode){ return retval;} /*  Nothing to delete  */
	retval = delnode->value;
	tree->freekey(delnode->key);

	/*  Node has two non-null children. Transform so not case */
	if (NULL!=delnode->right && NULL!=delnode->left){
		RBNODE leftmost = minnode_rbtree_sub(delnode->right);
		delnode->key = leftmost->key;
		delnode->value = leftmost->value;
		delnode = leftmost;
	}

	/* delnode now has at most one child  */
	enum rbcolour delcol = delnode->colour;
	RBNODE child = (NULL==delnode->right)?delnode->left:delnode->right;
	if ( NULL==child){
		child = create_rbnode(black); /* "Phantom node" */
		phantom = child;
	}
	/*  Replace node with child  */
	if (NULL!=delnode->parent){
		if   (delnode->parent->left==delnode) delnode->parent->left = child;
		else if (delnode->parent->right==delnode) delnode->parent->right = child;
		else abort();
	} else {
		tree->root = child;
	}
	child->parent = delnode->parent;
	free(delnode);

	if(red==delcol){ goto remove_end;}
	/*  Deleted node was black  */
	if (red==colour_rbnode(child)){ child->colour = black; goto remove_end;}

case1:
	/* Case 1 */
	if ( NULL==child->parent){ /* New root */
		tree->root = child;
		goto remove_end;
	}
	
	/* Case 2 */
	RBNODE sibling = sibling_rbnode(child);
	if ( red==colour_rbnode(sibling)){
		child->parent->colour = red;
		sibling->colour = black;
		if ( child == child->parent->left) rotate_left_rbtree (child->parent,tree);
		else rotate_right_rbtree(child->parent,tree);
	}
	sibling = sibling_rbnode(child);
	assert(sibling->colour==black);

	/*  Case 3 */
	if ( black== child->parent->colour
	  && black==colour_rbnode(sibling->left) && black==colour_rbnode(sibling->right)){
		sibling->colour = red;
		child = child->parent;
		goto case1;
	}
	assert(sibling->colour==black);

	/*  Case 4 */
	if ( red == child->parent->colour
	  && black==colour_rbnode(sibling->left) && black==colour_rbnode(sibling->right)){
		sibling->colour = red;
		child->parent->colour = black;
		goto remove_end;
	}
	assert(sibling->colour == black);

	/*  Case 5 */
	if ( child==child->parent->left
	  && red==colour_rbnode(sibling->left) && black==colour_rbnode(sibling->right)){
		sibling->colour = red;
		sibling->left->colour = black;
		rotate_right_rbtree(sibling,tree);
	} else if ( child==child->parent->right
	  && black==colour_rbnode(sibling->left) && red==colour_rbnode(sibling->right)){
		sibling->colour = red;
		sibling->right->colour = black;
		rotate_left_rbtree(sibling,tree);
	}
	sibling = sibling_rbnode(child);


	/*  Case 6 */
	sibling->colour = child->parent->colour;
	child->parent->colour = black;
	if ( child == child->parent->left){
		sibling->right->colour = black;
		rotate_left_rbtree(child->parent,tree);
	} else {
		sibling->left->colour = black;
		rotate_right_rbtree(child->parent,tree);
	}

remove_end:
	/*  Delelte phantom node */
	if ( phantom ){
		if ( NULL!=phantom->parent){
			if      (phantom->parent->left == phantom) phantom->parent->left = NULL;
			else if (phantom->parent->right == phantom) phantom->parent->right = NULL;
			else abort();
		}
		if(tree->root==phantom){tree->root = NULL;}
		free(phantom);
	}
	return retval;
}