Пример #1
0
int rb_remove ( const RB_TYPE *rbt, RB_TREE *root, void *data ) {
    RB_NODE *node = *root;
    if ( node != NULL ) {
	RB_NODE head = {{0,0},0}; /* False tree root */
	RB_NODE *q, *p, *g; /* Helpers */
	RB_NODE *f = NULL;  /* Found item */
	int dir = 1, cmp;
 
	/* Set up helpers */
	q = &head;
	g = p = NULL;
	q->link[1] = node;
 
	/* Search and push a red down */
	while ( q->link[dir] != NULL ) {
	    int last = dir;
 
	    /* Update helpers */
	    g = p, p = q;
	    q = q->link[dir];
	    cmp = (*rbt->cmp)(rbt->ctx,q+1,data);
	    dir = cmp < 0;
 
	    /* Save found node */
	    if ( cmp == 0 )
		f = q;
 
	    /* Push the red node down */
	    if ( !is_red ( q ) && !is_red ( q->link[dir] ) ) {
		if ( is_red ( q->link[!dir] ) )
		    p = p->link[last] = rb_single ( q, dir );
		else if ( !is_red ( q->link[!dir] ) ) {
		    RB_NODE *s = p->link[!last];
 
		    if ( s != NULL ) {
			if ( !is_red ( s->link[!last] ) && !is_red ( s->link[last] ) ) {
			    /* Color flip */
			    p->red = 0;
			    s->red = 1;
			    q->red = 1;
			    }
			else {
			    int dir2 = g->link[1] == p;
 
			    if ( is_red ( s->link[last] ) )
				g->link[dir2] = rb_double ( p, last );
			    else if ( is_red ( s->link[!last] ) )
				g->link[dir2] = rb_single ( p, last );
 
			    /* Ensure correct coloring */
			    q->red = g->link[dir2]->red = 1;
			    g->link[dir2]->link[0]->red = 0;
			    g->link[dir2]->link[1]->red = 0;
			    }
			}
		    }
		}
	    }
 
	/* Replace and remove if found */
	if ( f != NULL ) {
	    if (f!=q) memcpy(f+1,q+1,rbt->iSize-sizeof(RB_NODE));
	    p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
	    if ( !rbt->delnode ) free(q);
	    else (*rbt->delnode)(rbt->ctx,q);
	    }
 
	/* Update root and make it black */
	*root = node = head.link[1];
	if ( node != NULL )
	    node->red = 0;
	}
 
    return 1;
    }
Пример #2
0
int rb_insert( const RB_TYPE *rbt, RB_TREE *root, void *data ) {
    RB_NODE *node = *root;
    int cmp;
    int ins = 0;
    if ( node == NULL ) {
	/* Empty tree case */
	*root = node = make_node(rbt,data);
	assert(node!=NULL);
	ins = 1;
	}
    else {
	RB_NODE head = {{0,0},0}; /* False tree root */
 
	RB_NODE *g, *t;     /* Grandparent & parent */
	RB_NODE *p, *q;     /* Iterator & parent */
	int dir = 0, last=0;
 
	/* Set up helpers */
	t = &head;
	g = p = NULL;
	q = t->link[1] = node;
 
	/* Search down the tree */
	for ( ; ; ) {
	    if ( q == NULL ) {
		/* Insert new node at the bottom */
		p->link[dir] = q = make_node(rbt,data);
		assert(q!=NULL);
		ins = 1;
		}
	    else if ( is_red ( q->link[0] ) && is_red ( q->link[1] ) ) {
		/* Color flip */
		q->red = 1;
		q->link[0]->red = 0;
		q->link[1]->red = 0;
		}
 
	    /* Fix red violation */
	    if ( is_red ( q ) && is_red ( p ) ) {
		int dir2 = t->link[1] == g;
 
		if ( q == p->link[last] )
		    t->link[dir2] = rb_single ( g, !last );
		else
		    t->link[dir2] = rb_double ( g, !last );
		}
 
	    /* Stop if found */
	    cmp = (*rbt->cmp)(rbt->ctx,q+1,data);
	    if ( cmp == 0 )
		break;
 
	    last = dir;
	    dir = cmp < 0;
 
	    /* Update helpers */
	    if ( g != NULL )
		t = g;
	    g = p, p = q;
	    q = q->link[dir];
	    }
 
	/* Update root */
	*root = node = head.link[1];
	}
 
    /* Make root black */
    node->red = 0;
 
    return ins;
    }
Пример #3
0
extern int
rb_remove(node_t **rootaddr, node_t *_node)
{
	PyObject *key = KEY(_node);
	node_t *root = *rootaddr;

	node_t head = { { NULL } }; /* False tree root */
	node_t *q, *p, *g; /* Helpers */
	node_t *f = NULL; /* Found item */
	node_t *tmp;
	int dir = 1;

	if (root == NULL)
		return 0;

	/* Set up our helpers */
	q = &head;
	g = p = NULL;
	RIGHT_NODE(q) = root;

	/*
	 Search and push a red node down
	 to fix red violations as we go
	 */
	while (q->link[dir] != NULL) {
		int last = dir;
		int cmp_res;

		/* Move the helpers down */
		g = p, p = q;
		q = q->link[dir];

		cmp_res =  ct_compare(KEY(q), key);

		dir = cmp_res < 0;

		/*
		 Save the node with matching data and keep
		 going; we'll do removal tasks at the end
		 */
		if (cmp_res == 0)
			f = q;

		/* Push the red node down with rotations and color flips */
		if (!is_red(q) && !is_red(q->link[dir])) {
			if (is_red(q->link[!dir])) {
				tmp = rb_single(q, dir);
				PARENT_NODE(tmp) = p;
				p = p->link[last] = tmp;
			}
			else if (!is_red(q->link[!dir])) {
				node_t *s = p->link[!last];

				if (s != NULL) {
					if (!is_red(s->link[!last]) &&
						!is_red(s->link[last])) {
						/* Color flip */
						RED(p) = 0;
						RED(s) = 1;
						RED(q) = 1;
					}
					else {
						int dir2 = g->link[1] == p;

						if (is_red(s->link[last])) {
							tmp = g->link[dir2] = rb_double(p, last);
							PARENT_NODE(tmp) = g;
						}
						else if (is_red(s->link[!last])) {
							tmp = g->link[dir2] = rb_single(p, last);
							PARENT_NODE(tmp) = g;
						}

						/* Ensure correct coloring */
						RED(q) = RED(g->link[dir2]) = 1;
						RED(g->link[dir2]->link[0]) = 0;
						RED(g->link[dir2]->link[1]) = 0;
					}
				}
			}
		}
	}

	/* Replace and remove the saved node */
	if (f != NULL) {
		ct_swap_data(f, q);
		p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
		ct_delete_node(q);
	}

	/* Update the root (it may be different) */
	root = head.link[1];

	/* Make the root black for simplified logic */
	if (root != NULL) {
		RED(root) = 0;
		PARENT_NODE(root) = NULL;
	}
	*rootaddr = root;
	return (f != NULL);
}
Пример #4
0
extern int
rb_insert(node_t **rootaddr, PyObject *key, PyObject *value)
{
    int new_node = 0;
	node_t *root = *rootaddr;

	if (root == NULL) {
		// case 1, root == NULL
		root = rb_new_node(NULL, key, value);
		new_node = 1;
		if (root == NULL)
			return -1; // got no memory
	}
	else {
		node_t head; /* False tree root */
		node_t *g, *t; /* Grandparent & parent */
		node_t *p, *q; /* Iterator & parent */
		int dir = 0;
		int last = 0;

		/* Set up our helpers */
		t = &head;
		g = NULL;
		p = NULL;
		RIGHT_NODE(t) = root;
		LEFT_NODE(t) = NULL;
		q = RIGHT_NODE(t);

		/* Search down the tree for a place to insert */
		for (;;) {
			int cmp_res;
			if (q == NULL) {
				/* Insert a new node at the first null link */
				q = rb_new_node(p, key, value);
				new_node = 1;
				p->link[dir] = q;
				if (q == NULL)
					return -1; // get no memory
			}
			else if (is_red(q->link[0]) && is_red(q->link[1])) {
				/* Simple red violation: color flip */
				RED(q) = 1;
				RED(q->link[0]) = 0;
				RED(q->link[1]) = 0;
			}

			if (is_red(q) && is_red(p)) {
				/* Hard red violation: rotations necessary */
				int dir2 = (t->link[1] == g);

				if (q == p->link[last]) {
					node_t * tmp = t->link[dir2] = rb_single(g, !last);
					PARENT_NODE(tmp) = t; 
				} else {
					node_t *tmp = t->link[dir2] = rb_double(g, !last);
					PARENT_NODE(tmp) = t; 
				}
			}

			/*  Stop working if we inserted a new node. */
			if (new_node)
				break;

			cmp_res = ct_compare(KEY(q), key);
			if (cmp_res == 0) {       /* if key exists            */
				// Py_XDECREF(VALUE(q)); /* release old value object */
				// VALUE(q) = value;      set new value object     
				// Py_INCREF(value);     /* take new value object    */
				break;
			}
			last = dir;
			dir = (cmp_res < 0);

			/* Move the helpers down */
			if (g != NULL)
				t = g;

			g = p;
			p = q;
			q = q->link[dir];
		}
		/* Update the root (it may be different) */
		root = head.link[1];
	}

	/* Make the root black for simplified logic */
	RED(root) = 0;
	(*rootaddr) = root;
	PARENT_NODE(root) = NULL; 
	return new_node;
}
Пример #5
0
extern int
rb_remove(node_t **rootaddr, PyObject *key)
{
	node_t *root = *rootaddr;

	node_t head = { { NULL } }; 
	node_t *q, *p, *g; 
	node_t *f = NULL; 
	int dir = 1;

	if (root == NULL)
		return 0;

	
	q = &head;
	g = p = NULL;
	RIGHT_NODE(q) = root;

	while (q->link[dir] != NULL) {
		int last = dir;
		int cmp_res;

		
		g = p, p = q;
		q = q->link[dir];

		cmp_res =  ct_compare(KEY(q), key);

		dir = cmp_res < 0;

		if (cmp_res == 0)
			f = q;

		
		if (!is_red(q) && !is_red(q->link[dir])) {
			if (is_red(q->link[!dir]))
				p = p->link[last] = rb_single(q, dir);
			else if (!is_red(q->link[!dir])) {
				node_t *s = p->link[!last];

				if (s != NULL) {
					if (!is_red(s->link[!last]) &&
						!is_red(s->link[last])) {
						
						RED(p) = 0;
						RED(s) = 1;
						RED(q) = 1;
					}
					else {
						int dir2 = g->link[1] == p;

						if (is_red(s->link[last]))
							g->link[dir2] = rb_double(p, last);
						else if (is_red(s->link[!last]))
							g->link[dir2] = rb_single(p, last);

						
						RED(q) = RED(g->link[dir2]) = 1;
						RED(g->link[dir2]->link[0]) = 0;
						RED(g->link[dir2]->link[1]) = 0;
					}
				}
			}
		}
	}

	
	if (f != NULL) {
		ct_swap_data(f, q);
		p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
		ct_delete_node(q);
	}

	
	root = head.link[1];

	
	if (root != NULL)
		RED(root) = 0;
	*rootaddr = root;
	return (f != NULL);
}
Пример #6
0
extern int
rb_insert(node_t **rootaddr, PyObject *key, PyObject *value)
{
	node_t *root = *rootaddr;

	if (root == NULL) {
		root = rb_new_node(key, value);
		if (root == NULL)
			return -1; 
	}
	else {
		node_t head; 
		node_t *g, *t; 
		node_t *p, *q; 
		int dir = 0;
		int last = 0;
		int new_node = 0;

		
		t = &head;
		g = NULL;
		p = NULL;
		RIGHT_NODE(t) = root;
		LEFT_NODE(t) = NULL;
		q = RIGHT_NODE(t);

		
		for (;;) {
			int cmp_res;
			if (q == NULL) {
				
				q = rb_new_node(key, value);
				p->link[dir] = q;
				new_node = 1;
				if (q == NULL)
					return -1; 
			}
			else if (is_red(q->link[0]) && is_red(q->link[1])) {
				
				RED(q) = 1;
				RED(q->link[0]) = 0;
				RED(q->link[1]) = 0;
			}

			if (is_red(q) && is_red(p)) {
				
				int dir2 = (t->link[1] == g);

				if (q == p->link[last])
					t->link[dir2] = rb_single(g, !last);
				else
					t->link[dir2] = rb_double(g, !last);
			}

			
			if (new_node)
				break;

			cmp_res = ct_compare(KEY(q), key);
			if (cmp_res == 0) {       
				Py_XDECREF(VALUE(q)); 
				VALUE(q) = value;     
				Py_INCREF(value);     
				return 0;
			}
			last = dir;
			dir = (cmp_res < 0);

			
			if (g != NULL)
				t = g;

			g = p;
			p = q;
			q = q->link[dir];
		}
		
		root = head.link[1];
	}

	
	RED(root) = 0;
	(*rootaddr) = root;
	return 1;
}