Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * rbtree.c -- generic red black tree
      3  *
      4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
      5  *
      6  * See LICENSE for the license.
      7  *
      8  */
      9 
     10 #include "config.h"
     11 
     12 #include <assert.h>
     13 #include <stdlib.h>
     14 
     15 #include "rbtree.h"
     16 
     17 #define	BLACK	0
     18 #define	RED	1
     19 
     20 rbnode_type	rbtree_null_node = {
     21 	RBTREE_NULL,		/* Parent.  */
     22 	RBTREE_NULL,		/* Left.  */
     23 	RBTREE_NULL,		/* Right.  */
     24 	NULL,			/* Key.  */
     25 	BLACK			/* Color.  */
     26 };
     27 
     28 static void rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node);
     29 static void rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node);
     30 static void rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node);
     31 static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child, rbnode_type* child_parent);
     32 
     33 /*
     34  * Creates a new red black tree, initializes and returns a pointer to it.
     35  *
     36  * Return NULL on failure.
     37  *
     38  */
     39 rbtree_type *
     40 rbtree_create (region_type *region, int (*cmpf)(const void *, const void *))
     41 {
     42 	rbtree_type *rbtree;
     43 
     44 	/* Allocate memory for it */
     45 	rbtree = (rbtree_type *) region_alloc(region, sizeof(rbtree_type));
     46 	if (!rbtree) {
     47 		return NULL;
     48 	}
     49 
     50 	/* Initialize it */
     51 	rbtree->root = RBTREE_NULL;
     52 	rbtree->count = 0;
     53 	rbtree->region = region;
     54 	rbtree->cmp = cmpf;
     55 
     56 	return rbtree;
     57 }
     58 
     59 /*
     60  * Rotates the node to the left.
     61  *
     62  */
     63 static void
     64 rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node)
     65 {
     66 	rbnode_type *right;
     67 
     68 	/* Check if rbtree is NULL */
     69 	if (!rbtree) {
     70 		return;
     71 	}
     72 	right = node->right;
     73 	node->right = right->left;
     74 	if (right->left != RBTREE_NULL)
     75 		right->left->parent = node;
     76 
     77 	right->parent = node->parent;
     78 
     79 	if (node->parent != RBTREE_NULL) {
     80 		if (node == node->parent->left) {
     81 			node->parent->left = right;
     82 		} else  {
     83 			node->parent->right = right;
     84 		}
     85 	} else {
     86 		rbtree->root = right;
     87 	}
     88 	right->left = node;
     89 	node->parent = right;
     90 }
     91 
     92 /*
     93  * Rotates the node to the right.
     94  *
     95  */
     96 static void
     97 rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node)
     98 {
     99 	rbnode_type *left;
    100 
    101 	/* Check if rbtree is NULL */
    102 	if (!rbtree) {
    103 		return;
    104 	}
    105 	left = node->left;
    106 	node->left = left->right;
    107 	if (left->right != RBTREE_NULL)
    108 		left->right->parent = node;
    109 
    110 	left->parent = node->parent;
    111 
    112 	if (node->parent != RBTREE_NULL) {
    113 		if (node == node->parent->right) {
    114 			node->parent->right = left;
    115 		} else  {
    116 			node->parent->left = left;
    117 		}
    118 	} else {
    119 		rbtree->root = left;
    120 	}
    121 	left->right = node;
    122 	node->parent = left;
    123 }
    124 
    125 static void
    126 rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node)
    127 {
    128 	rbnode_type	*uncle;
    129 
    130 	/* Check if rbtree is NULL */
    131 	if (!rbtree) {
    132 		return;
    133 	}
    134 
    135 	/* While not at the root and need fixing... */
    136 	while (node != rbtree->root && node->parent->color == RED) {
    137 		/* If our parent is left child of our grandparent... */
    138 		if (node->parent == node->parent->parent->left) {
    139 			uncle = node->parent->parent->right;
    140 
    141 			/* If our uncle is red... */
    142 			if (uncle->color == RED) {
    143 				/* Paint the parent and the uncle black... */
    144 				node->parent->color = BLACK;
    145 				uncle->color = BLACK;
    146 
    147 				/* And the grandparent red... */
    148 				node->parent->parent->color = RED;
    149 
    150 				/* And continue fixing the grandparent */
    151 				node = node->parent->parent;
    152 			} else {				/* Our uncle is black... */
    153 				/* Are we the right child? */
    154 				if (node == node->parent->right) {
    155 					node = node->parent;
    156 					rbtree_rotate_left(rbtree, node);
    157 				}
    158 				/* Now we're the left child, repaint and rotate... */
    159 				node->parent->color = BLACK;
    160 				node->parent->parent->color = RED;
    161 				rbtree_rotate_right(rbtree, node->parent->parent);
    162 			}
    163 		} else {
    164 			uncle = node->parent->parent->left;
    165 
    166 			/* If our uncle is red... */
    167 			if (uncle->color == RED) {
    168 				/* Paint the parent and the uncle black... */
    169 				node->parent->color = BLACK;
    170 				uncle->color = BLACK;
    171 
    172 				/* And the grandparent red... */
    173 				node->parent->parent->color = RED;
    174 
    175 				/* And continue fixing the grandparent */
    176 				node = node->parent->parent;
    177 			} else {				/* Our uncle is black... */
    178 				/* Are we the right child? */
    179 				if (node == node->parent->left) {
    180 					node = node->parent;
    181 					rbtree_rotate_right(rbtree, node);
    182 				}
    183 				/* Now we're the right child, repaint and rotate... */
    184 				node->parent->color = BLACK;
    185 				node->parent->parent->color = RED;
    186 				rbtree_rotate_left(rbtree, node->parent->parent);
    187 			}
    188 		}
    189 	}
    190 	rbtree->root->color = BLACK;
    191 }
    192 
    193 
    194 /*
    195  * Inserts a node into a red black tree.
    196  *
    197  * Returns NULL on failure or the pointer to the newly added node
    198  * otherwise.
    199  */
    200 rbnode_type *
    201 rbtree_insert (rbtree_type *rbtree, rbnode_type *data)
    202 {
    203 	/* XXX Not necessary, but keeps compiler quiet... */
    204 	int r = 0;
    205 	rbnode_type	*node;
    206 	rbnode_type	*parent;
    207 
    208 	/* Check if rbtree is NULL */
    209 	if (!rbtree) {
    210 		return NULL;
    211 	}
    212 
    213 	/* We start at the root of the tree */
    214 	node = rbtree->root;
    215 	parent = RBTREE_NULL;
    216 
    217 	/* Lets find the new parent... */
    218 	while (node != RBTREE_NULL) {
    219 		/* Compare two keys, do we have a duplicate? */
    220 		if ((r = rbtree->cmp(data->key, node->key)) == 0) {
    221 			return NULL;
    222 		}
    223 		parent = node;
    224 
    225 		if (r < 0) {
    226 			node = node->left;
    227 		} else {
    228 			node = node->right;
    229 		}
    230 	}
    231 
    232 	/* Initialize the new node */
    233 	data->parent = parent;
    234 	data->left = data->right = RBTREE_NULL;
    235 	data->color = RED;
    236 	rbtree->count++;
    237 
    238 	/* Insert it into the tree... */
    239 	if (parent != RBTREE_NULL) {
    240 		if (r < 0) {
    241 			parent->left = data;
    242 		} else {
    243 			parent->right = data;
    244 		}
    245 	} else {
    246 		rbtree->root = data;
    247 	}
    248 
    249 	/* Fix up the red-black properties... */
    250 	rbtree_insert_fixup(rbtree, data);
    251 
    252 	return data;
    253 }
    254 
    255 /*
    256  * Searches the red black tree, returns the data if key is found or NULL otherwise.
    257  *
    258  */
    259 rbnode_type *
    260 rbtree_search (rbtree_type *rbtree, const void *key)
    261 {
    262 	rbnode_type *node;
    263 
    264 	/* Check if rbtree is NULL */
    265 	if (!rbtree) {
    266 		return NULL;
    267 	}
    268 
    269 	if (rbtree_find_less_equal(rbtree, key, &node)) {
    270 		return node;
    271 	} else {
    272 		return NULL;
    273 	}
    274 }
    275 
    276 /* helpers for delete */
    277 static void swap_int8(uint8_t* x, uint8_t* y)
    278 {
    279 	uint8_t t = *x; *x = *y; *y = t;
    280 }
    281 
    282 static void swap_np(rbnode_type** x, rbnode_type** y)
    283 {
    284 	rbnode_type* t = *x; *x = *y; *y = t;
    285 }
    286 
    287 static void change_parent_ptr(rbtree_type* rbtree, rbnode_type* parent, rbnode_type* old, rbnode_type* new)
    288 {
    289 	/* Check if rbtree is NULL */
    290 	if (!rbtree) {
    291 		return;
    292 	}
    293 
    294 	if(parent == RBTREE_NULL)
    295 	{
    296 		assert(rbtree->root == old);
    297 		if(rbtree->root == old) rbtree->root = new;
    298 		return;
    299 	}
    300 	assert(parent->left == old || parent->right == old
    301 		|| parent->left == new || parent->right == new);
    302 	if(parent->left == old) parent->left = new;
    303 	if(parent->right == old) parent->right = new;
    304 }
    305 static void change_child_ptr(rbnode_type* child, rbnode_type* old, rbnode_type* new)
    306 {
    307 	if(child == RBTREE_NULL) return;
    308 	assert(child->parent == old || child->parent == new);
    309 	if(child->parent == old) child->parent = new;
    310 }
    311 
    312 rbnode_type*
    313 rbtree_delete(rbtree_type *rbtree, const void *key)
    314 {
    315 	rbnode_type *to_delete;
    316 	rbnode_type *child;
    317 
    318 	/* Check if rbtree is NULL */
    319 	if (!rbtree) {
    320 		return NULL;
    321 	}
    322 
    323 	if((to_delete = rbtree_search(rbtree, key)) == 0) return 0;
    324 	rbtree->count--;
    325 
    326 	/* make sure we have at most one non-leaf child */
    327 	if(to_delete->left != RBTREE_NULL && to_delete->right != RBTREE_NULL)
    328 	{
    329 		/* swap with smallest from right subtree (or largest from left) */
    330 		rbnode_type *smright = to_delete->right;
    331 		while(smright->left != RBTREE_NULL)
    332 			smright = smright->left;
    333 		/* swap the smright and to_delete elements in the tree,
    334 		 * but the rbnode_type is first part of user data struct
    335 		 * so cannot just swap the keys and data pointers. Instead
    336 		 * readjust the pointers left,right,parent */
    337 
    338 		/* swap colors - colors are tied to the position in the tree */
    339 		swap_int8(&to_delete->color, &smright->color);
    340 
    341 		/* swap child pointers in parents of smright/to_delete */
    342 		change_parent_ptr(rbtree, to_delete->parent, to_delete, smright);
    343 		if(to_delete->right != smright)
    344 			change_parent_ptr(rbtree, smright->parent, smright, to_delete);
    345 
    346 		/* swap parent pointers in children of smright/to_delete */
    347 		change_child_ptr(smright->left, smright, to_delete);
    348 		change_child_ptr(smright->left, smright, to_delete);
    349 		change_child_ptr(smright->right, smright, to_delete);
    350 		change_child_ptr(smright->right, smright, to_delete);
    351 		change_child_ptr(to_delete->left, to_delete, smright);
    352 		if(to_delete->right != smright)
    353 			change_child_ptr(to_delete->right, to_delete, smright);
    354 		if(to_delete->right == smright)
    355 		{
    356 			/* set up so after swap they work */
    357 			to_delete->right = to_delete;
    358 			smright->parent = smright;
    359 		}
    360 
    361 		/* swap pointers in to_delete/smright nodes */
    362 		swap_np(&to_delete->parent, &smright->parent);
    363 		swap_np(&to_delete->left, &smright->left);
    364 		swap_np(&to_delete->right, &smright->right);
    365 
    366 		/* now delete to_delete (which is at the location where the smright previously was) */
    367 	}
    368 	assert(to_delete->left == RBTREE_NULL || to_delete->right == RBTREE_NULL);
    369 
    370 	if(to_delete->left != RBTREE_NULL) child = to_delete->left;
    371 	else child = to_delete->right;
    372 
    373 	/* unlink to_delete from the tree, replace to_delete with child */
    374 	change_parent_ptr(rbtree, to_delete->parent, to_delete, child);
    375 	change_child_ptr(child, to_delete, to_delete->parent);
    376 
    377 	if(to_delete->color == RED)
    378 	{
    379 		/* if node is red then the child (black) can be swapped in */
    380 	}
    381 	else if(child->color == RED)
    382 	{
    383 		/* change child to BLACK, removing a RED node is no problem */
    384 		if(child!=RBTREE_NULL) child->color = BLACK;
    385 	}
    386 	else rbtree_delete_fixup(rbtree, child, to_delete->parent);
    387 
    388 	/* unlink completely */
    389 	to_delete->parent = RBTREE_NULL;
    390 	to_delete->left = RBTREE_NULL;
    391 	to_delete->right = RBTREE_NULL;
    392 	to_delete->color = BLACK;
    393 	return to_delete;
    394 }
    395 
    396 static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child, rbnode_type* child_parent)
    397 {
    398 	rbnode_type* sibling;
    399 	int go_up = 1;
    400 
    401 	/* Check if rbtree is NULL */
    402 	if (!rbtree) {
    403 		return;
    404 	}
    405 
    406 	/* determine sibling to the node that is one-black short */
    407 	if(child_parent->right == child) sibling = child_parent->left;
    408 	else sibling = child_parent->right;
    409 
    410 	while(go_up)
    411 	{
    412 		if(child_parent == RBTREE_NULL)
    413 		{
    414 			/* removed parent==black from root, every path, so ok */
    415 			return;
    416 		}
    417 
    418 		if(sibling->color == RED)
    419 		{	/* rotate to get a black sibling */
    420 			child_parent->color = RED;
    421 			sibling->color = BLACK;
    422 			if(child_parent->right == child)
    423 				rbtree_rotate_right(rbtree, child_parent);
    424 			else	rbtree_rotate_left(rbtree, child_parent);
    425 			/* new sibling after rotation */
    426 			if(child_parent->right == child) sibling = child_parent->left;
    427 			else sibling = child_parent->right;
    428 		}
    429 
    430 		if(child_parent->color == BLACK
    431 			&& sibling->color == BLACK
    432 			&& sibling->left->color == BLACK
    433 			&& sibling->right->color == BLACK)
    434 		{	/* fixup local with recolor of sibling */
    435 			if(sibling != RBTREE_NULL)
    436 				sibling->color = RED;
    437 
    438 			child = child_parent;
    439 			child_parent = child_parent->parent;
    440 			/* prepare to go up, new sibling */
    441 			if(child_parent->right == child) sibling = child_parent->left;
    442 			else sibling = child_parent->right;
    443 		}
    444 		else go_up = 0;
    445 	}
    446 
    447 	if(child_parent->color == RED
    448 		&& sibling->color == BLACK
    449 		&& sibling->left->color == BLACK
    450 		&& sibling->right->color == BLACK)
    451 	{
    452 		/* move red to sibling to rebalance */
    453 		if(sibling != RBTREE_NULL)
    454 			sibling->color = RED;
    455 		child_parent->color = BLACK;
    456 		return;
    457 	}
    458 	assert(sibling != RBTREE_NULL);
    459 
    460 	/* get a new sibling, by rotating at sibling. See which child
    461 	   of sibling is red */
    462 	if(child_parent->right == child
    463 		&& sibling->color == BLACK
    464 		&& sibling->right->color == RED
    465 		&& sibling->left->color == BLACK)
    466 	{
    467 		sibling->color = RED;
    468 		sibling->right->color = BLACK;
    469 		rbtree_rotate_left(rbtree, sibling);
    470 		/* new sibling after rotation */
    471 		if(child_parent->right == child) sibling = child_parent->left;
    472 		else sibling = child_parent->right;
    473 	}
    474 	else if(child_parent->left == child
    475 		&& sibling->color == BLACK
    476 		&& sibling->left->color == RED
    477 		&& sibling->right->color == BLACK)
    478 	{
    479 		sibling->color = RED;
    480 		sibling->left->color = BLACK;
    481 		rbtree_rotate_right(rbtree, sibling);
    482 		/* new sibling after rotation */
    483 		if(child_parent->right == child) sibling = child_parent->left;
    484 		else sibling = child_parent->right;
    485 	}
    486 
    487 	/* now we have a black sibling with a red child. rotate and exchange colors. */
    488 	sibling->color = child_parent->color;
    489 	child_parent->color = BLACK;
    490 	if(child_parent->right == child)
    491 	{
    492 		assert(sibling->left->color == RED);
    493 		sibling->left->color = BLACK;
    494 		rbtree_rotate_right(rbtree, child_parent);
    495 	}
    496 	else
    497 	{
    498 		assert(sibling->right->color == RED);
    499 		sibling->right->color = BLACK;
    500 		rbtree_rotate_left(rbtree, child_parent);
    501 	}
    502 }
    503 
    504 int
    505 rbtree_find_less_equal(rbtree_type *rbtree, const void *key, rbnode_type **result)
    506 {
    507 	int r;
    508 	rbnode_type *node;
    509 
    510 	assert(result);
    511 
    512 	/* Check if rbtree is NULL */
    513 	if (!rbtree) {
    514 		*result = NULL;
    515 		return 0;
    516 	}
    517 
    518 	/* We start at root... */
    519 	node = rbtree->root;
    520 
    521 	*result = NULL;
    522 
    523 	/* While there are children... */
    524 	while (node != RBTREE_NULL) {
    525 		r = rbtree->cmp(key, node->key);
    526 		if (r == 0) {
    527 			/* Exact match */
    528 			*result = node;
    529 			return 1;
    530 		}
    531 		if (r < 0) {
    532 			node = node->left;
    533 		} else {
    534 			/* Temporary match */
    535 			*result = node;
    536 			node = node->right;
    537 		}
    538 	}
    539 	return 0;
    540 }
    541 
    542 /*
    543  * Finds the first element in the red black tree
    544  *
    545  */
    546 rbnode_type *
    547 rbtree_first (rbtree_type *rbtree)
    548 {
    549 	rbnode_type *node;
    550 
    551 	/* Check if rbtree is NULL */
    552 	if (!rbtree) {
    553 		return NULL;
    554 	}
    555 
    556 	for (node = rbtree->root; node->left != RBTREE_NULL; node = node->left);
    557 	return node;
    558 }
    559 
    560 rbnode_type *
    561 rbtree_last (rbtree_type *rbtree)
    562 {
    563 	rbnode_type *node;
    564 
    565 	/* Check if rbtree is NULL */
    566 	if (!rbtree) {
    567 		return NULL;
    568 	}
    569 
    570 	for (node = rbtree->root; node->right != RBTREE_NULL; node = node->right);
    571 	return node;
    572 }
    573 
    574 /*
    575  * Returns the next node...
    576  *
    577  */
    578 rbnode_type *
    579 rbtree_next (rbnode_type *node)
    580 {
    581 	rbnode_type *parent;
    582 
    583 	if (node->right != RBTREE_NULL) {
    584 		/* One right, then keep on going left... */
    585 		for (node = node->right; node->left != RBTREE_NULL; node = node->left);
    586 	} else {
    587 		parent = node->parent;
    588 		while (parent != RBTREE_NULL && node == parent->right) {
    589 			node = parent;
    590 			parent = parent->parent;
    591 		}
    592 		node = parent;
    593 	}
    594 	return node;
    595 }
    596 
    597 rbnode_type *
    598 rbtree_previous(rbnode_type *node)
    599 {
    600 	rbnode_type *parent;
    601 
    602 	if (node->left != RBTREE_NULL) {
    603 		/* One left, then keep on going right... */
    604 		for (node = node->left; node->right != RBTREE_NULL; node = node->right);
    605 	} else {
    606 		parent = node->parent;
    607 		while (parent != RBTREE_NULL && node == parent->left) {
    608 			node = parent;
    609 			parent = parent->parent;
    610 		}
    611 		node = parent;
    612 	}
    613 	return node;
    614 }
    615