162ac0c33Sjakob /*
262ac0c33Sjakob * rbtree.c -- generic red black tree
362ac0c33Sjakob *
4d3fecca9Ssthen * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
562ac0c33Sjakob *
662ac0c33Sjakob * See LICENSE for the license.
762ac0c33Sjakob *
862ac0c33Sjakob */
962ac0c33Sjakob
10aee1b7aaSsthen #include "config.h"
1162ac0c33Sjakob
1262ac0c33Sjakob #include <assert.h>
1362ac0c33Sjakob #include <stdlib.h>
1462ac0c33Sjakob
1562ac0c33Sjakob #include "rbtree.h"
1662ac0c33Sjakob
1762ac0c33Sjakob #define BLACK 0
1862ac0c33Sjakob #define RED 1
1962ac0c33Sjakob
20*fe5fe5f6Sflorian rbnode_type rbtree_null_node = {
2162ac0c33Sjakob RBTREE_NULL, /* Parent. */
2262ac0c33Sjakob RBTREE_NULL, /* Left. */
2362ac0c33Sjakob RBTREE_NULL, /* Right. */
2462ac0c33Sjakob NULL, /* Key. */
2562ac0c33Sjakob BLACK /* Color. */
2662ac0c33Sjakob };
2762ac0c33Sjakob
28*fe5fe5f6Sflorian static void rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node);
29*fe5fe5f6Sflorian static void rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node);
30*fe5fe5f6Sflorian static void rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node);
31*fe5fe5f6Sflorian static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child, rbnode_type* child_parent);
3262ac0c33Sjakob
3362ac0c33Sjakob /*
342fd875a4Ssthen * Creates a new red black tree, initializes and returns a pointer to it.
3562ac0c33Sjakob *
3662ac0c33Sjakob * Return NULL on failure.
3762ac0c33Sjakob *
3862ac0c33Sjakob */
39*fe5fe5f6Sflorian rbtree_type *
rbtree_create(region_type * region,int (* cmpf)(const void *,const void *))4062ac0c33Sjakob rbtree_create (region_type *region, int (*cmpf)(const void *, const void *))
4162ac0c33Sjakob {
42*fe5fe5f6Sflorian rbtree_type *rbtree;
4362ac0c33Sjakob
4462ac0c33Sjakob /* Allocate memory for it */
45*fe5fe5f6Sflorian rbtree = (rbtree_type *) region_alloc(region, sizeof(rbtree_type));
4662ac0c33Sjakob if (!rbtree) {
4762ac0c33Sjakob return NULL;
4862ac0c33Sjakob }
4962ac0c33Sjakob
5062ac0c33Sjakob /* Initialize it */
5162ac0c33Sjakob rbtree->root = RBTREE_NULL;
5262ac0c33Sjakob rbtree->count = 0;
5362ac0c33Sjakob rbtree->region = region;
5462ac0c33Sjakob rbtree->cmp = cmpf;
5562ac0c33Sjakob
5662ac0c33Sjakob return rbtree;
5762ac0c33Sjakob }
5862ac0c33Sjakob
5962ac0c33Sjakob /*
6062ac0c33Sjakob * Rotates the node to the left.
6162ac0c33Sjakob *
6262ac0c33Sjakob */
6362ac0c33Sjakob static void
rbtree_rotate_left(rbtree_type * rbtree,rbnode_type * node)64*fe5fe5f6Sflorian rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node)
6562ac0c33Sjakob {
66*fe5fe5f6Sflorian rbnode_type *right = node->right;
6762ac0c33Sjakob node->right = right->left;
6862ac0c33Sjakob if (right->left != RBTREE_NULL)
6962ac0c33Sjakob right->left->parent = node;
7062ac0c33Sjakob
7162ac0c33Sjakob right->parent = node->parent;
7262ac0c33Sjakob
7362ac0c33Sjakob if (node->parent != RBTREE_NULL) {
7462ac0c33Sjakob if (node == node->parent->left) {
7562ac0c33Sjakob node->parent->left = right;
7662ac0c33Sjakob } else {
7762ac0c33Sjakob node->parent->right = right;
7862ac0c33Sjakob }
7962ac0c33Sjakob } else {
8062ac0c33Sjakob rbtree->root = right;
8162ac0c33Sjakob }
8262ac0c33Sjakob right->left = node;
8362ac0c33Sjakob node->parent = right;
8462ac0c33Sjakob }
8562ac0c33Sjakob
8662ac0c33Sjakob /*
8762ac0c33Sjakob * Rotates the node to the right.
8862ac0c33Sjakob *
8962ac0c33Sjakob */
9062ac0c33Sjakob static void
rbtree_rotate_right(rbtree_type * rbtree,rbnode_type * node)91*fe5fe5f6Sflorian rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node)
9262ac0c33Sjakob {
93*fe5fe5f6Sflorian rbnode_type *left = node->left;
9462ac0c33Sjakob node->left = left->right;
9562ac0c33Sjakob if (left->right != RBTREE_NULL)
9662ac0c33Sjakob left->right->parent = node;
9762ac0c33Sjakob
9862ac0c33Sjakob left->parent = node->parent;
9962ac0c33Sjakob
10062ac0c33Sjakob if (node->parent != RBTREE_NULL) {
10162ac0c33Sjakob if (node == node->parent->right) {
10262ac0c33Sjakob node->parent->right = left;
10362ac0c33Sjakob } else {
10462ac0c33Sjakob node->parent->left = left;
10562ac0c33Sjakob }
10662ac0c33Sjakob } else {
10762ac0c33Sjakob rbtree->root = left;
10862ac0c33Sjakob }
10962ac0c33Sjakob left->right = node;
11062ac0c33Sjakob node->parent = left;
11162ac0c33Sjakob }
11262ac0c33Sjakob
11362ac0c33Sjakob static void
rbtree_insert_fixup(rbtree_type * rbtree,rbnode_type * node)114*fe5fe5f6Sflorian rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node)
11562ac0c33Sjakob {
116*fe5fe5f6Sflorian rbnode_type *uncle;
11762ac0c33Sjakob
11862ac0c33Sjakob /* While not at the root and need fixing... */
11962ac0c33Sjakob while (node != rbtree->root && node->parent->color == RED) {
12062ac0c33Sjakob /* If our parent is left child of our grandparent... */
12162ac0c33Sjakob if (node->parent == node->parent->parent->left) {
12262ac0c33Sjakob uncle = node->parent->parent->right;
12362ac0c33Sjakob
12462ac0c33Sjakob /* If our uncle is red... */
12562ac0c33Sjakob if (uncle->color == RED) {
12662ac0c33Sjakob /* Paint the parent and the uncle black... */
12762ac0c33Sjakob node->parent->color = BLACK;
12862ac0c33Sjakob uncle->color = BLACK;
12962ac0c33Sjakob
13062ac0c33Sjakob /* And the grandparent red... */
13162ac0c33Sjakob node->parent->parent->color = RED;
13262ac0c33Sjakob
13362ac0c33Sjakob /* And continue fixing the grandparent */
13462ac0c33Sjakob node = node->parent->parent;
13562ac0c33Sjakob } else { /* Our uncle is black... */
13662ac0c33Sjakob /* Are we the right child? */
13762ac0c33Sjakob if (node == node->parent->right) {
13862ac0c33Sjakob node = node->parent;
13962ac0c33Sjakob rbtree_rotate_left(rbtree, node);
14062ac0c33Sjakob }
14162ac0c33Sjakob /* Now we're the left child, repaint and rotate... */
14262ac0c33Sjakob node->parent->color = BLACK;
14362ac0c33Sjakob node->parent->parent->color = RED;
14462ac0c33Sjakob rbtree_rotate_right(rbtree, node->parent->parent);
14562ac0c33Sjakob }
14662ac0c33Sjakob } else {
14762ac0c33Sjakob uncle = node->parent->parent->left;
14862ac0c33Sjakob
14962ac0c33Sjakob /* If our uncle is red... */
15062ac0c33Sjakob if (uncle->color == RED) {
15162ac0c33Sjakob /* Paint the parent and the uncle black... */
15262ac0c33Sjakob node->parent->color = BLACK;
15362ac0c33Sjakob uncle->color = BLACK;
15462ac0c33Sjakob
15562ac0c33Sjakob /* And the grandparent red... */
15662ac0c33Sjakob node->parent->parent->color = RED;
15762ac0c33Sjakob
15862ac0c33Sjakob /* And continue fixing the grandparent */
15962ac0c33Sjakob node = node->parent->parent;
16062ac0c33Sjakob } else { /* Our uncle is black... */
16162ac0c33Sjakob /* Are we the right child? */
16262ac0c33Sjakob if (node == node->parent->left) {
16362ac0c33Sjakob node = node->parent;
16462ac0c33Sjakob rbtree_rotate_right(rbtree, node);
16562ac0c33Sjakob }
16662ac0c33Sjakob /* Now we're the right child, repaint and rotate... */
16762ac0c33Sjakob node->parent->color = BLACK;
16862ac0c33Sjakob node->parent->parent->color = RED;
16962ac0c33Sjakob rbtree_rotate_left(rbtree, node->parent->parent);
17062ac0c33Sjakob }
17162ac0c33Sjakob }
17262ac0c33Sjakob }
17362ac0c33Sjakob rbtree->root->color = BLACK;
17462ac0c33Sjakob }
17562ac0c33Sjakob
17662ac0c33Sjakob
17762ac0c33Sjakob /*
17862ac0c33Sjakob * Inserts a node into a red black tree.
17962ac0c33Sjakob *
18062ac0c33Sjakob * Returns NULL on failure or the pointer to the newly added node
18162ac0c33Sjakob * otherwise.
18262ac0c33Sjakob */
183*fe5fe5f6Sflorian rbnode_type *
rbtree_insert(rbtree_type * rbtree,rbnode_type * data)184*fe5fe5f6Sflorian rbtree_insert (rbtree_type *rbtree, rbnode_type *data)
18562ac0c33Sjakob {
18662ac0c33Sjakob /* XXX Not necessary, but keeps compiler quiet... */
18762ac0c33Sjakob int r = 0;
18862ac0c33Sjakob
18962ac0c33Sjakob /* We start at the root of the tree */
190*fe5fe5f6Sflorian rbnode_type *node = rbtree->root;
191*fe5fe5f6Sflorian rbnode_type *parent = RBTREE_NULL;
19262ac0c33Sjakob
19362ac0c33Sjakob /* Lets find the new parent... */
19462ac0c33Sjakob while (node != RBTREE_NULL) {
19562ac0c33Sjakob /* Compare two keys, do we have a duplicate? */
19662ac0c33Sjakob if ((r = rbtree->cmp(data->key, node->key)) == 0) {
19762ac0c33Sjakob return NULL;
19862ac0c33Sjakob }
19962ac0c33Sjakob parent = node;
20062ac0c33Sjakob
20162ac0c33Sjakob if (r < 0) {
20262ac0c33Sjakob node = node->left;
20362ac0c33Sjakob } else {
20462ac0c33Sjakob node = node->right;
20562ac0c33Sjakob }
20662ac0c33Sjakob }
20762ac0c33Sjakob
20862ac0c33Sjakob /* Initialize the new node */
20962ac0c33Sjakob data->parent = parent;
21062ac0c33Sjakob data->left = data->right = RBTREE_NULL;
21162ac0c33Sjakob data->color = RED;
21262ac0c33Sjakob rbtree->count++;
21362ac0c33Sjakob
21462ac0c33Sjakob /* Insert it into the tree... */
21562ac0c33Sjakob if (parent != RBTREE_NULL) {
21662ac0c33Sjakob if (r < 0) {
21762ac0c33Sjakob parent->left = data;
21862ac0c33Sjakob } else {
21962ac0c33Sjakob parent->right = data;
22062ac0c33Sjakob }
22162ac0c33Sjakob } else {
22262ac0c33Sjakob rbtree->root = data;
22362ac0c33Sjakob }
22462ac0c33Sjakob
22562ac0c33Sjakob /* Fix up the red-black properties... */
22662ac0c33Sjakob rbtree_insert_fixup(rbtree, data);
22762ac0c33Sjakob
22862ac0c33Sjakob return data;
22962ac0c33Sjakob }
23062ac0c33Sjakob
23162ac0c33Sjakob /*
23262ac0c33Sjakob * Searches the red black tree, returns the data if key is found or NULL otherwise.
23362ac0c33Sjakob *
23462ac0c33Sjakob */
235*fe5fe5f6Sflorian rbnode_type *
rbtree_search(rbtree_type * rbtree,const void * key)236*fe5fe5f6Sflorian rbtree_search (rbtree_type *rbtree, const void *key)
23762ac0c33Sjakob {
238*fe5fe5f6Sflorian rbnode_type *node;
23962ac0c33Sjakob
24062ac0c33Sjakob if (rbtree_find_less_equal(rbtree, key, &node)) {
24162ac0c33Sjakob return node;
24262ac0c33Sjakob } else {
24362ac0c33Sjakob return NULL;
24462ac0c33Sjakob }
24562ac0c33Sjakob }
24662ac0c33Sjakob
24762ac0c33Sjakob /* helpers for delete */
swap_int8(uint8_t * x,uint8_t * y)24862ac0c33Sjakob static void swap_int8(uint8_t* x, uint8_t* y)
24962ac0c33Sjakob {
25062ac0c33Sjakob uint8_t t = *x; *x = *y; *y = t;
25162ac0c33Sjakob }
25262ac0c33Sjakob
swap_np(rbnode_type ** x,rbnode_type ** y)253*fe5fe5f6Sflorian static void swap_np(rbnode_type** x, rbnode_type** y)
25462ac0c33Sjakob {
255*fe5fe5f6Sflorian rbnode_type* t = *x; *x = *y; *y = t;
25662ac0c33Sjakob }
25762ac0c33Sjakob
change_parent_ptr(rbtree_type * rbtree,rbnode_type * parent,rbnode_type * old,rbnode_type * new)258*fe5fe5f6Sflorian static void change_parent_ptr(rbtree_type* rbtree, rbnode_type* parent, rbnode_type* old, rbnode_type* new)
25962ac0c33Sjakob {
26062ac0c33Sjakob if(parent == RBTREE_NULL)
26162ac0c33Sjakob {
26262ac0c33Sjakob assert(rbtree->root == old);
26362ac0c33Sjakob if(rbtree->root == old) rbtree->root = new;
26462ac0c33Sjakob return;
26562ac0c33Sjakob }
26662ac0c33Sjakob assert(parent->left == old || parent->right == old
26762ac0c33Sjakob || parent->left == new || parent->right == new);
26862ac0c33Sjakob if(parent->left == old) parent->left = new;
26962ac0c33Sjakob if(parent->right == old) parent->right = new;
27062ac0c33Sjakob }
change_child_ptr(rbnode_type * child,rbnode_type * old,rbnode_type * new)271*fe5fe5f6Sflorian static void change_child_ptr(rbnode_type* child, rbnode_type* old, rbnode_type* new)
27262ac0c33Sjakob {
27362ac0c33Sjakob if(child == RBTREE_NULL) return;
27462ac0c33Sjakob assert(child->parent == old || child->parent == new);
27562ac0c33Sjakob if(child->parent == old) child->parent = new;
27662ac0c33Sjakob }
27762ac0c33Sjakob
278*fe5fe5f6Sflorian rbnode_type*
rbtree_delete(rbtree_type * rbtree,const void * key)279*fe5fe5f6Sflorian rbtree_delete(rbtree_type *rbtree, const void *key)
28062ac0c33Sjakob {
281*fe5fe5f6Sflorian rbnode_type *to_delete;
282*fe5fe5f6Sflorian rbnode_type *child;
28362ac0c33Sjakob if((to_delete = rbtree_search(rbtree, key)) == 0) return 0;
28462ac0c33Sjakob rbtree->count--;
28562ac0c33Sjakob
28662ac0c33Sjakob /* make sure we have at most one non-leaf child */
28762ac0c33Sjakob if(to_delete->left != RBTREE_NULL && to_delete->right != RBTREE_NULL)
28862ac0c33Sjakob {
28962ac0c33Sjakob /* swap with smallest from right subtree (or largest from left) */
290*fe5fe5f6Sflorian rbnode_type *smright = to_delete->right;
29162ac0c33Sjakob while(smright->left != RBTREE_NULL)
29262ac0c33Sjakob smright = smright->left;
29362ac0c33Sjakob /* swap the smright and to_delete elements in the tree,
294*fe5fe5f6Sflorian * but the rbnode_type is first part of user data struct
29562ac0c33Sjakob * so cannot just swap the keys and data pointers. Instead
29662ac0c33Sjakob * readjust the pointers left,right,parent */
29762ac0c33Sjakob
29862ac0c33Sjakob /* swap colors - colors are tied to the position in the tree */
29962ac0c33Sjakob swap_int8(&to_delete->color, &smright->color);
30062ac0c33Sjakob
30162ac0c33Sjakob /* swap child pointers in parents of smright/to_delete */
30262ac0c33Sjakob change_parent_ptr(rbtree, to_delete->parent, to_delete, smright);
30362ac0c33Sjakob if(to_delete->right != smright)
30462ac0c33Sjakob change_parent_ptr(rbtree, smright->parent, smright, to_delete);
30562ac0c33Sjakob
30662ac0c33Sjakob /* swap parent pointers in children of smright/to_delete */
30762ac0c33Sjakob change_child_ptr(smright->left, smright, to_delete);
30862ac0c33Sjakob change_child_ptr(smright->left, smright, to_delete);
30962ac0c33Sjakob change_child_ptr(smright->right, smright, to_delete);
31062ac0c33Sjakob change_child_ptr(smright->right, smright, to_delete);
31162ac0c33Sjakob change_child_ptr(to_delete->left, to_delete, smright);
31262ac0c33Sjakob if(to_delete->right != smright)
31362ac0c33Sjakob change_child_ptr(to_delete->right, to_delete, smright);
31462ac0c33Sjakob if(to_delete->right == smright)
31562ac0c33Sjakob {
31662ac0c33Sjakob /* set up so after swap they work */
31762ac0c33Sjakob to_delete->right = to_delete;
31862ac0c33Sjakob smright->parent = smright;
31962ac0c33Sjakob }
32062ac0c33Sjakob
32162ac0c33Sjakob /* swap pointers in to_delete/smright nodes */
32262ac0c33Sjakob swap_np(&to_delete->parent, &smright->parent);
32362ac0c33Sjakob swap_np(&to_delete->left, &smright->left);
32462ac0c33Sjakob swap_np(&to_delete->right, &smright->right);
32562ac0c33Sjakob
32662ac0c33Sjakob /* now delete to_delete (which is at the location where the smright previously was) */
32762ac0c33Sjakob }
32862ac0c33Sjakob assert(to_delete->left == RBTREE_NULL || to_delete->right == RBTREE_NULL);
32962ac0c33Sjakob
33062ac0c33Sjakob if(to_delete->left != RBTREE_NULL) child = to_delete->left;
33162ac0c33Sjakob else child = to_delete->right;
33262ac0c33Sjakob
33362ac0c33Sjakob /* unlink to_delete from the tree, replace to_delete with child */
33462ac0c33Sjakob change_parent_ptr(rbtree, to_delete->parent, to_delete, child);
33562ac0c33Sjakob change_child_ptr(child, to_delete, to_delete->parent);
33662ac0c33Sjakob
33762ac0c33Sjakob if(to_delete->color == RED)
33862ac0c33Sjakob {
33962ac0c33Sjakob /* if node is red then the child (black) can be swapped in */
34062ac0c33Sjakob }
34162ac0c33Sjakob else if(child->color == RED)
34262ac0c33Sjakob {
34362ac0c33Sjakob /* change child to BLACK, removing a RED node is no problem */
34462ac0c33Sjakob if(child!=RBTREE_NULL) child->color = BLACK;
34562ac0c33Sjakob }
34662ac0c33Sjakob else rbtree_delete_fixup(rbtree, child, to_delete->parent);
34762ac0c33Sjakob
34862ac0c33Sjakob /* unlink completely */
34962ac0c33Sjakob to_delete->parent = RBTREE_NULL;
35062ac0c33Sjakob to_delete->left = RBTREE_NULL;
35162ac0c33Sjakob to_delete->right = RBTREE_NULL;
35262ac0c33Sjakob to_delete->color = BLACK;
35362ac0c33Sjakob return to_delete;
35462ac0c33Sjakob }
35562ac0c33Sjakob
rbtree_delete_fixup(rbtree_type * rbtree,rbnode_type * child,rbnode_type * child_parent)356*fe5fe5f6Sflorian static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child, rbnode_type* child_parent)
35762ac0c33Sjakob {
358*fe5fe5f6Sflorian rbnode_type* sibling;
35962ac0c33Sjakob int go_up = 1;
36062ac0c33Sjakob
36162ac0c33Sjakob /* determine sibling to the node that is one-black short */
36262ac0c33Sjakob if(child_parent->right == child) sibling = child_parent->left;
36362ac0c33Sjakob else sibling = child_parent->right;
36462ac0c33Sjakob
36562ac0c33Sjakob while(go_up)
36662ac0c33Sjakob {
36762ac0c33Sjakob if(child_parent == RBTREE_NULL)
36862ac0c33Sjakob {
36962ac0c33Sjakob /* removed parent==black from root, every path, so ok */
37062ac0c33Sjakob return;
37162ac0c33Sjakob }
37262ac0c33Sjakob
37362ac0c33Sjakob if(sibling->color == RED)
37462ac0c33Sjakob { /* rotate to get a black sibling */
37562ac0c33Sjakob child_parent->color = RED;
37662ac0c33Sjakob sibling->color = BLACK;
37762ac0c33Sjakob if(child_parent->right == child)
37862ac0c33Sjakob rbtree_rotate_right(rbtree, child_parent);
37962ac0c33Sjakob else rbtree_rotate_left(rbtree, child_parent);
38062ac0c33Sjakob /* new sibling after rotation */
38162ac0c33Sjakob if(child_parent->right == child) sibling = child_parent->left;
38262ac0c33Sjakob else sibling = child_parent->right;
38362ac0c33Sjakob }
38462ac0c33Sjakob
38562ac0c33Sjakob if(child_parent->color == BLACK
38662ac0c33Sjakob && sibling->color == BLACK
38762ac0c33Sjakob && sibling->left->color == BLACK
38862ac0c33Sjakob && sibling->right->color == BLACK)
38962ac0c33Sjakob { /* fixup local with recolor of sibling */
39062ac0c33Sjakob if(sibling != RBTREE_NULL)
39162ac0c33Sjakob sibling->color = RED;
39262ac0c33Sjakob
39362ac0c33Sjakob child = child_parent;
39462ac0c33Sjakob child_parent = child_parent->parent;
39562ac0c33Sjakob /* prepare to go up, new sibling */
39662ac0c33Sjakob if(child_parent->right == child) sibling = child_parent->left;
39762ac0c33Sjakob else sibling = child_parent->right;
39862ac0c33Sjakob }
39962ac0c33Sjakob else go_up = 0;
40062ac0c33Sjakob }
40162ac0c33Sjakob
40262ac0c33Sjakob if(child_parent->color == RED
40362ac0c33Sjakob && sibling->color == BLACK
40462ac0c33Sjakob && sibling->left->color == BLACK
40562ac0c33Sjakob && sibling->right->color == BLACK)
40662ac0c33Sjakob {
40762ac0c33Sjakob /* move red to sibling to rebalance */
40862ac0c33Sjakob if(sibling != RBTREE_NULL)
40962ac0c33Sjakob sibling->color = RED;
41062ac0c33Sjakob child_parent->color = BLACK;
41162ac0c33Sjakob return;
41262ac0c33Sjakob }
41362ac0c33Sjakob assert(sibling != RBTREE_NULL);
41462ac0c33Sjakob
41562ac0c33Sjakob /* get a new sibling, by rotating at sibling. See which child
41662ac0c33Sjakob of sibling is red */
41762ac0c33Sjakob if(child_parent->right == child
41862ac0c33Sjakob && sibling->color == BLACK
41962ac0c33Sjakob && sibling->right->color == RED
42062ac0c33Sjakob && sibling->left->color == BLACK)
42162ac0c33Sjakob {
42262ac0c33Sjakob sibling->color = RED;
42362ac0c33Sjakob sibling->right->color = BLACK;
42462ac0c33Sjakob rbtree_rotate_left(rbtree, sibling);
42562ac0c33Sjakob /* new sibling after rotation */
42662ac0c33Sjakob if(child_parent->right == child) sibling = child_parent->left;
42762ac0c33Sjakob else sibling = child_parent->right;
42862ac0c33Sjakob }
42962ac0c33Sjakob else if(child_parent->left == child
43062ac0c33Sjakob && sibling->color == BLACK
43162ac0c33Sjakob && sibling->left->color == RED
43262ac0c33Sjakob && sibling->right->color == BLACK)
43362ac0c33Sjakob {
43462ac0c33Sjakob sibling->color = RED;
43562ac0c33Sjakob sibling->left->color = BLACK;
43662ac0c33Sjakob rbtree_rotate_right(rbtree, sibling);
43762ac0c33Sjakob /* new sibling after rotation */
43862ac0c33Sjakob if(child_parent->right == child) sibling = child_parent->left;
43962ac0c33Sjakob else sibling = child_parent->right;
44062ac0c33Sjakob }
44162ac0c33Sjakob
44262ac0c33Sjakob /* now we have a black sibling with a red child. rotate and exchange colors. */
44362ac0c33Sjakob sibling->color = child_parent->color;
44462ac0c33Sjakob child_parent->color = BLACK;
44562ac0c33Sjakob if(child_parent->right == child)
44662ac0c33Sjakob {
44762ac0c33Sjakob assert(sibling->left->color == RED);
44862ac0c33Sjakob sibling->left->color = BLACK;
44962ac0c33Sjakob rbtree_rotate_right(rbtree, child_parent);
45062ac0c33Sjakob }
45162ac0c33Sjakob else
45262ac0c33Sjakob {
45362ac0c33Sjakob assert(sibling->right->color == RED);
45462ac0c33Sjakob sibling->right->color = BLACK;
45562ac0c33Sjakob rbtree_rotate_left(rbtree, child_parent);
45662ac0c33Sjakob }
45762ac0c33Sjakob }
45862ac0c33Sjakob
45962ac0c33Sjakob int
rbtree_find_less_equal(rbtree_type * rbtree,const void * key,rbnode_type ** result)460*fe5fe5f6Sflorian rbtree_find_less_equal(rbtree_type *rbtree, const void *key, rbnode_type **result)
46162ac0c33Sjakob {
46262ac0c33Sjakob int r;
463*fe5fe5f6Sflorian rbnode_type *node;
46462ac0c33Sjakob
46562ac0c33Sjakob assert(result);
46662ac0c33Sjakob
46762ac0c33Sjakob /* We start at root... */
46862ac0c33Sjakob node = rbtree->root;
46962ac0c33Sjakob
47062ac0c33Sjakob *result = NULL;
47162ac0c33Sjakob
47262ac0c33Sjakob /* While there are children... */
47362ac0c33Sjakob while (node != RBTREE_NULL) {
47462ac0c33Sjakob r = rbtree->cmp(key, node->key);
47562ac0c33Sjakob if (r == 0) {
47662ac0c33Sjakob /* Exact match */
47762ac0c33Sjakob *result = node;
47862ac0c33Sjakob return 1;
47962ac0c33Sjakob }
48062ac0c33Sjakob if (r < 0) {
48162ac0c33Sjakob node = node->left;
48262ac0c33Sjakob } else {
48362ac0c33Sjakob /* Temporary match */
48462ac0c33Sjakob *result = node;
48562ac0c33Sjakob node = node->right;
48662ac0c33Sjakob }
48762ac0c33Sjakob }
48862ac0c33Sjakob return 0;
48962ac0c33Sjakob }
49062ac0c33Sjakob
49162ac0c33Sjakob /*
49262ac0c33Sjakob * Finds the first element in the red black tree
49362ac0c33Sjakob *
49462ac0c33Sjakob */
495*fe5fe5f6Sflorian rbnode_type *
rbtree_first(rbtree_type * rbtree)496*fe5fe5f6Sflorian rbtree_first (rbtree_type *rbtree)
49762ac0c33Sjakob {
498*fe5fe5f6Sflorian rbnode_type *node;
49962ac0c33Sjakob
50062ac0c33Sjakob for (node = rbtree->root; node->left != RBTREE_NULL; node = node->left);
50162ac0c33Sjakob return node;
50262ac0c33Sjakob }
50362ac0c33Sjakob
504*fe5fe5f6Sflorian rbnode_type *
rbtree_last(rbtree_type * rbtree)505*fe5fe5f6Sflorian rbtree_last (rbtree_type *rbtree)
50662ac0c33Sjakob {
507*fe5fe5f6Sflorian rbnode_type *node;
50862ac0c33Sjakob
50962ac0c33Sjakob for (node = rbtree->root; node->right != RBTREE_NULL; node = node->right);
51062ac0c33Sjakob return node;
51162ac0c33Sjakob }
51262ac0c33Sjakob
51362ac0c33Sjakob /*
51462ac0c33Sjakob * Returns the next node...
51562ac0c33Sjakob *
51662ac0c33Sjakob */
517*fe5fe5f6Sflorian rbnode_type *
rbtree_next(rbnode_type * node)518*fe5fe5f6Sflorian rbtree_next (rbnode_type *node)
51962ac0c33Sjakob {
520*fe5fe5f6Sflorian rbnode_type *parent;
52162ac0c33Sjakob
52262ac0c33Sjakob if (node->right != RBTREE_NULL) {
52362ac0c33Sjakob /* One right, then keep on going left... */
52462ac0c33Sjakob for (node = node->right; node->left != RBTREE_NULL; node = node->left);
52562ac0c33Sjakob } else {
52662ac0c33Sjakob parent = node->parent;
52762ac0c33Sjakob while (parent != RBTREE_NULL && node == parent->right) {
52862ac0c33Sjakob node = parent;
52962ac0c33Sjakob parent = parent->parent;
53062ac0c33Sjakob }
53162ac0c33Sjakob node = parent;
53262ac0c33Sjakob }
53362ac0c33Sjakob return node;
53462ac0c33Sjakob }
53562ac0c33Sjakob
536*fe5fe5f6Sflorian rbnode_type *
rbtree_previous(rbnode_type * node)537*fe5fe5f6Sflorian rbtree_previous(rbnode_type *node)
53862ac0c33Sjakob {
539*fe5fe5f6Sflorian rbnode_type *parent;
54062ac0c33Sjakob
54162ac0c33Sjakob if (node->left != RBTREE_NULL) {
54262ac0c33Sjakob /* One left, then keep on going right... */
54362ac0c33Sjakob for (node = node->left; node->right != RBTREE_NULL; node = node->right);
54462ac0c33Sjakob } else {
54562ac0c33Sjakob parent = node->parent;
54662ac0c33Sjakob while (parent != RBTREE_NULL && node == parent->left) {
54762ac0c33Sjakob node = parent;
54862ac0c33Sjakob parent = parent->parent;
54962ac0c33Sjakob }
55062ac0c33Sjakob node = parent;
55162ac0c33Sjakob }
55262ac0c33Sjakob return node;
55362ac0c33Sjakob }
554