2 a talloc based red-black tree
4 Copyright (C) Ronnie Sahlberg 2007
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #define NO_MEMORY_FATAL(p) do { if (!(p)) { \
24 DEBUG(0,("Out of memory for %s at %s\n", #p, __location__)); \
30 trbt_create(TALLOC_CTX *memctx)
34 tree = talloc_zero(memctx, trbt_tree_t);
35 NO_MEMORY_FATAL(tree);
40 static inline trbt_node_t *
41 trbt_parent(trbt_node_t *node)
46 static inline trbt_node_t *
47 trbt_grandparent(trbt_node_t *node)
51 parent=trbt_parent(node);
53 return parent->parent;
58 static inline trbt_node_t *
59 trbt_uncle(trbt_node_t *node)
61 trbt_node_t *parent, *grandparent;
63 parent=trbt_parent(node);
67 grandparent=trbt_parent(parent);
71 if(parent==grandparent->left){
72 return grandparent->right;
74 return grandparent->left;
78 static inline void trbt_insert_case1(trbt_tree_t *tree, trbt_node_t *node);
79 static inline void trbt_insert_case2(trbt_tree_t *tree, trbt_node_t *node);
82 trbt_rotate_left(trbt_node_t *node)
84 trbt_tree_t *tree = node->tree;
87 if(node->parent->left==node){
88 node->parent->left=node->right;
90 node->parent->right=node->right;
93 tree->root=node->right;
95 node->right->parent=node->parent;
96 node->parent=node->right;
97 node->right=node->right->left;
99 node->right->parent=node;
101 node->parent->left=node;
105 trbt_rotate_right(trbt_node_t *node)
107 trbt_tree_t *tree = node->tree;
110 if(node->parent->left==node){
111 node->parent->left=node->left;
113 node->parent->right=node->left;
116 tree->root=node->left;
118 node->left->parent=node->parent;
119 node->parent=node->left;
120 node->left=node->left->right;
122 node->left->parent=node;
124 node->parent->right=node;
127 /* NULL nodes are black by definition */
128 static inline int trbt_get_color(trbt_node_t *node)
133 return node->rb_color;
135 static inline int trbt_get_color_left(trbt_node_t *node)
140 if (node->left==NULL) {
143 return node->left->rb_color;
145 static inline int trbt_get_color_right(trbt_node_t *node)
150 if (node->right==NULL) {
153 return node->right->rb_color;
155 /* setting a NULL node to black is a nop */
156 static inline void trbt_set_color(trbt_node_t *node, int color)
158 if ( (node==NULL) && (color==TRBT_BLACK) ) {
161 node->rb_color = color;
163 static inline void trbt_set_color_left(trbt_node_t *node, int color)
165 if ( ((node==NULL)||(node->left==NULL)) && (color==TRBT_BLACK) ) {
168 node->left->rb_color = color;
170 static inline void trbt_set_color_right(trbt_node_t *node, int color)
172 if ( ((node==NULL)||(node->right==NULL)) && (color==TRBT_BLACK) ) {
175 node->right->rb_color = color;
179 trbt_insert_case5(trbt_tree_t *tree, trbt_node_t *node)
181 trbt_node_t *grandparent;
184 parent=trbt_parent(node);
185 grandparent=trbt_parent(parent);
186 parent->rb_color=TRBT_BLACK;
187 grandparent->rb_color=TRBT_RED;
188 if( (node==parent->left) && (parent==grandparent->left) ){
189 trbt_rotate_right(grandparent);
191 trbt_rotate_left(grandparent);
196 trbt_insert_case4(trbt_tree_t *tree, trbt_node_t *node)
198 trbt_node_t *grandparent;
201 parent=trbt_parent(node);
202 grandparent=trbt_parent(parent);
206 if( (node==parent->right) && (parent==grandparent->left) ){
207 trbt_rotate_left(parent);
209 } else if( (node==parent->left) && (parent==grandparent->right) ){
210 trbt_rotate_right(parent);
213 trbt_insert_case5(tree, node);
217 trbt_insert_case3(trbt_tree_t *tree, trbt_node_t *node)
219 trbt_node_t *grandparent;
223 uncle=trbt_uncle(node);
224 if(uncle && (uncle->rb_color==TRBT_RED)){
225 parent=trbt_parent(node);
226 parent->rb_color=TRBT_BLACK;
227 uncle->rb_color=TRBT_BLACK;
228 grandparent=trbt_grandparent(node);
229 grandparent->rb_color=TRBT_RED;
230 trbt_insert_case1(tree, grandparent);
232 trbt_insert_case4(tree, node);
237 trbt_insert_case2(trbt_tree_t *tree, trbt_node_t *node)
241 parent=trbt_parent(node);
242 /* parent is always non-NULL here */
243 if(parent->rb_color==TRBT_BLACK){
246 trbt_insert_case3(tree, node);
250 trbt_insert_case1(trbt_tree_t *tree, trbt_node_t *node)
254 parent=trbt_parent(node);
256 node->rb_color=TRBT_BLACK;
259 trbt_insert_case2(tree, node);
262 static inline trbt_node_t *
263 trbt_sibling(trbt_node_t *node)
267 parent=trbt_parent(node);
272 if (node == parent->left) {
273 return parent->right;
280 trbt_delete_case6(trbt_node_t *node)
282 trbt_node_t *sibling, *parent;
284 sibling = trbt_sibling(node);
285 parent = trbt_parent(node);
287 trbt_set_color(sibling, parent->rb_color);
288 trbt_set_color(parent, TRBT_BLACK);
289 if (node == parent->left) {
290 trbt_set_color_right(sibling, TRBT_BLACK);
291 trbt_rotate_left(parent);
293 trbt_set_color_left(sibling, TRBT_BLACK);
294 trbt_rotate_right(parent);
300 trbt_delete_case5(trbt_node_t *node)
302 trbt_node_t *parent, *sibling;
304 parent = trbt_parent(node);
305 sibling = trbt_sibling(node);
306 if ( (node == parent->left)
307 &&(trbt_get_color(sibling) == TRBT_BLACK)
308 &&(trbt_get_color_left(sibling) == TRBT_RED)
309 &&(trbt_get_color_right(sibling) == TRBT_BLACK) ){
310 trbt_set_color(sibling, TRBT_RED);
311 trbt_set_color_left(sibling, TRBT_BLACK);
312 trbt_rotate_right(sibling);
313 trbt_delete_case6(node);
316 if ( (node == parent->right)
317 &&(trbt_get_color(sibling) == TRBT_BLACK)
318 &&(trbt_get_color_right(sibling) == TRBT_RED)
319 &&(trbt_get_color_left(sibling) == TRBT_BLACK) ){
320 trbt_set_color(sibling, TRBT_RED);
321 trbt_set_color_right(sibling, TRBT_BLACK);
322 trbt_rotate_left(sibling);
323 trbt_delete_case6(node);
327 trbt_delete_case6(node);
331 trbt_delete_case4(trbt_node_t *node)
333 trbt_node_t *sibling;
335 sibling = trbt_sibling(node);
336 if ( (trbt_get_color(node->parent) == TRBT_RED)
337 &&(trbt_get_color(sibling) == TRBT_BLACK)
338 &&(trbt_get_color_left(sibling) == TRBT_BLACK)
339 &&(trbt_get_color_right(sibling) == TRBT_BLACK) ){
340 trbt_set_color(sibling, TRBT_RED);
341 trbt_set_color(node->parent, TRBT_BLACK);
343 trbt_delete_case5(node);
347 static void trbt_delete_case1(trbt_node_t *node);
350 trbt_delete_case3(trbt_node_t *node)
352 trbt_node_t *sibling;
354 sibling = trbt_sibling(node);
355 if ( (trbt_get_color(node->parent) == TRBT_BLACK)
356 &&(trbt_get_color(sibling) == TRBT_BLACK)
357 &&(trbt_get_color_left(sibling) == TRBT_BLACK)
358 &&(trbt_get_color_right(sibling) == TRBT_BLACK) ){
359 trbt_set_color(sibling, TRBT_RED);
360 trbt_delete_case1(node->parent);
362 trbt_delete_case4(node);
367 trbt_delete_case2(trbt_node_t *node)
369 trbt_node_t *sibling;
371 sibling = trbt_sibling(node);
372 if (trbt_get_color(sibling) == TRBT_RED) {
373 trbt_set_color(node->parent, TRBT_RED);
374 trbt_set_color(sibling, TRBT_BLACK);
375 if (node == node->parent->left) {
376 trbt_rotate_left(node->parent);
378 trbt_rotate_right(node->parent);
381 trbt_delete_case3(node);
385 trbt_delete_case1(trbt_node_t *node)
390 trbt_delete_case2(node);
395 delete_node(trbt_node_t *node)
397 trbt_node_t *parent, *child, dc;
399 /* This node has two child nodes, then just copy the content
400 from the next smaller node with this node and delete the
402 The predecessor is guaranteed to have at most one child
403 node since its right arm must be NULL
404 (It must be NULL since we are its sucessor and we are above
407 if (node->left != NULL && node->right != NULL) {
408 /* This node has two children, just copy the data */
409 /* find the predecessor */
410 trbt_node_t *temp = node->left;
412 while (temp->right != NULL) {
416 /* swap the predecessor data and key with the node to
419 talloc_free(node->data);
420 node->data = talloc_steal(node, temp->data);
421 node->key32 = temp->key32;
424 /* then delete the temp node.
425 this node is guaranteed to have at least one leaf child */
431 /* There is at most one child to this node to be deleted */
437 /* If the node to be deleted did not have any child at all we
438 create a temporary dummy node for the child and mark it black.
439 Once the delete of the node is finished, we remove this dummy
440 node, which is simple to do since it is guaranteed that it will
441 still not have any children after the delete operation.
442 This is because we dont represent the leaf-nodes as actual nodes
443 in this implementation.
447 child->tree = node->tree;
450 child->rb_color=TRBT_BLACK;
454 /* replace node with child */
455 parent = trbt_parent(node);
457 if (parent->left == node) {
458 parent->left = child;
460 parent->right = child;
463 node->tree->root = child;
465 child->parent = node->parent;
468 if (node->rb_color == TRBT_BLACK) {
469 if (trbt_get_color(child) == TRBT_RED) {
470 child->rb_color = TRBT_BLACK;
472 trbt_delete_case1(child);
476 /* If we had to create a temporary dummy node to represent a black
477 leaf child we now has to delete it.
478 This is simple since this dummy node originally had no children
479 and we are guaranteed that it will also not have any children
480 after the node has been deleted and any possible rotations
483 The only special case is if this was the last node of the tree
484 in which case we have to reset the root to NULL as well.
485 Othervise it is enough to just unlink the child from its new
489 if (child->parent == NULL) {
490 node->tree->root = NULL;
491 } else if (child == child->parent->left) {
492 child->parent->left = NULL;
494 child->parent->right = NULL;
502 static inline trbt_node_t *
503 trbt_create_node(trbt_tree_t *tree, trbt_node_t *parent, uint32_t key, void *data)
507 node=talloc_zero(tree, trbt_node_t);
508 NO_MEMORY_FATAL(node);
511 node->rb_color=TRBT_BLACK;
516 node->data=talloc_steal(node, data);
521 /* insert a new node in the tree.
522 if there is already a node with a matching key in the tree
523 we replace it with the new data and return a pointer to the old data
524 in case the caller wants to take any special action
527 trbt_insert32(trbt_tree_t *tree, uint32_t key, void *data)
533 /* is this the first node ?*/
535 node = trbt_create_node(tree, NULL, key, data);
541 /* it was not the new root so walk the tree until we find where to
542 * insert this new leaf.
545 /* this node already exists, replace data and return the
548 if(key==node->key32){
551 old_data = node->data;
552 node->data = talloc_steal(node, data);
556 if(key<node->key32) {
558 /* new node to the left */
559 trbt_node_t *new_node;
561 new_node = trbt_create_node(tree, node, key, data);
570 if(key>node->key32) {
572 /* new node to the right */
573 trbt_node_t *new_node;
575 new_node = trbt_create_node(tree, node, key, data);
576 node->right=new_node;
585 /* node will now point to the newly created node */
586 node->rb_color=TRBT_RED;
587 trbt_insert_case1(tree, node);
592 trbt_lookup32(trbt_tree_t *tree, uint32_t key)
599 if(key==node->key32){
615 trbt_delete32(trbt_tree_t *tree, uint32_t key)
622 if(key==node->key32){
639 trbt_insert32_callback(trbt_tree_t *tree, uint32_t key, void *(*callback)(void *param, void *data), void *param)
645 /* is this the first node ?*/
647 node = trbt_create_node(tree, NULL, key,
648 callback(param, NULL));
654 /* it was not the new root so walk the tree until we find where to
655 * insert this new leaf.
658 /* this node already exists, replace data and return the
661 if(key==node->key32){
662 node->data = talloc_steal(node,
663 callback(param, node->data));
667 if(key<node->key32) {
669 /* new node to the left */
670 trbt_node_t *new_node;
672 new_node = trbt_create_node(tree, node, key,
673 callback(param, NULL));
682 if(key>node->key32) {
684 /* new node to the right */
685 trbt_node_t *new_node;
687 new_node = trbt_create_node(tree, node, key,
688 callback(param, NULL));
689 node->right=new_node;
698 /* node will now point to the newly created node */
699 node->rb_color=TRBT_RED;
700 trbt_insert_case1(tree, node);
706 struct trbt_array_param {
707 void *(*callback)(void *param, void *data);
713 static void *array_insert_callback(void *p, void *data)
715 struct trbt_array_param *param = (struct trbt_array_param *)p;
716 trbt_tree_t *tree = NULL;
719 /* if keylen has reached 0 we are done and can call the users
720 callback function with the users parameters
722 if (param->keylen == 0) {
723 return param->callback(param->param, data);
727 /* keylen is not zero yes so we must create/process more subtrees */
728 /* if data is NULL this means we did not yet have a subtree here
729 and we must create one.
732 /* create a new subtree and hang it off our current tree */
733 tree = trbt_create(param->tree);
735 /* we already have a subtree for this path */
736 tree = (trbt_tree_t *)data;
739 trbt_insertarray32_callback(tree, param->keylen, param->key, param->callback, param->param);
741 /* now return either the old tree we got in *data or the new tree
742 we created to our caller so he can update his pointer in his
743 tree to point to our subtree
750 /* insert into the tree using an array of uint32 as a key */
752 trbt_insertarray32_callback(trbt_tree_t *tree, uint32_t keylen, uint32_t *key, void *(*cb)(void *param, void *data), void *pm)
754 struct trbt_array_param tap;
756 /* keylen-1 and key[1] since the call to insert32 will consume the
757 first part of the key.
761 tap.keylen = keylen-1;
765 trbt_insert32_callback(tree, key[0], array_insert_callback, &tap);
769 /* lookup the tree using an array of uint32 as a key */
771 trbt_lookuparray32(trbt_tree_t *tree, uint32_t keylen, uint32_t *key)
773 /* if keylen is 1 we can do a regular lookup and return this to the
777 return trbt_lookup32(tree, key[0]);
780 /* we need to lookup the next subtree */
781 tree = trbt_lookup32(tree, key[0]);
783 /* the key does not exist, return NULL */
787 /* now lookup the next part of the key in our new tree */
788 return trbt_lookuparray32(tree, keylen-1, &key[1]);
792 /* delete a node from the tree using an array of uint32 as a key */
794 trbt_deletearray32(trbt_tree_t *tree, uint32_t keylen, uint32_t *key)
796 trbt_tree_t *next_tree;
798 /* if we have reached the leaftree we can just delete the node
802 trbt_delete32(tree, key[0]);
807 /* find the next subtree and recurse into it if it exists */
808 next_tree = trbt_lookup32(tree, key[0]);
809 if (next_tree == NULL) {
813 trbt_deletearray32(next_tree, keylen-1, &key[1]);
816 /* when we returned from recursing into the the subtree,
817 that subtree might have become empty in which case we can delete it
820 if (next_tree->root == NULL) {
821 trbt_delete32(tree, key[0]);
827 /* traverse a tree starting at node */
829 trbt_traversearray32_node(trbt_node_t *node, uint32_t keylen,
830 void (*callback)(void *param, void *data),
834 trbt_traversearray32_node(node->left, keylen, callback, param);
837 /* this is the smallest node in this subtree
838 if keylen is 0 this means we can just call the callback
839 otherwise we must pull the next subtree and traverse that one as well
842 callback(param, node->data);
844 trbt_traversearray32(node->data, keylen, callback, param);
848 trbt_traversearray32_node(node->right, keylen, callback, param);
853 /* traverse the tree using an array of uint32 as a key */
855 trbt_traversearray32(trbt_tree_t *tree, uint32_t keylen,
856 void (*callback)(void *param, void *data),
870 trbt_traversearray32_node(node, keylen-1, callback, param);
876 static void printtree(trbt_node_t *node, int levels)
879 if(node==NULL)return;
880 printtree(node->left, levels+1);
882 for(i=0;i<levels;i++)printf(" ");
883 printf("key:%d COLOR:%s\n",node->key32,node->rb_color==TRBT_BLACK?"BLACK":"RED");
885 printtree(node->right, levels+1);
889 void print_tree(trbt_tree_t *tree)
891 if(tree->tree==NULL){
892 printf("tree is empty\n");
896 printtree(tree->tree->left, 1);
897 printf("root node key:%d COLOR:%s\n",tree->tree->key32,tree->tree->rb_color==TRBT_BLACK?"BLACK":"RED");
898 printtree(tree->tree->right, 1);
912 tree=trbt_create(talloc_new(NULL));
915 printf("adding node %i\n",i);
916 trbt_insert32(tree, i, NULL);
919 printf("deleting node %i\n",3);
920 trbt_delete32(tree, 3);
923 printf("deleting node %i\n",i);
924 trbt_delete32(tree, i);
931 printf("iteration : %d\n",cnt);
933 printf("adding node %i\n",i);
934 trbt_insert32(tree, i, NULL);
938 printf("deleting node %i\n",i);
939 trbt_delete32(tree, i);