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(DEBUG_CRIT,("Out of memory for %s at %s\n", #p, __location__)); \
30 tree_destructor_traverse_node(TALLOC_CTX
*mem_ctx
, trbt_node_t
*node
)
32 talloc_set_destructor(node
, NULL
);
34 tree_destructor_traverse_node(mem_ctx
, node
->left
);
37 tree_destructor_traverse_node(mem_ctx
, node
->right
);
39 talloc_steal(mem_ctx
, node
);
43 destroy a tree and remove all its nodes
45 static int tree_destructor(trbt_tree_t
*tree
)
59 /* traverse the tree and remove the node destructor and steal
60 the node to the temporary context.
61 we dont want to use the existing destructor for the node
62 since that will remove the nodes one by one from the tree.
63 since the entire tree will be completely destroyed we dont care
64 if it is inconsistent or unbalanced while freeing the
67 tmp_ctx
= talloc_new(NULL
);
68 tree_destructor_traverse_node(tmp_ctx
, node
);
75 /* create a red black tree */
77 trbt_create(TALLOC_CTX
*memctx
, uint32_t flags
)
81 tree
= talloc_zero(memctx
, trbt_tree_t
);
82 NO_MEMORY_FATAL(tree
);
84 /* If the tree is freed, we must walk over all entries and steal the
85 node from the stored data pointer and release the node.
86 Note, when we free the tree we only free the tree and not any of
87 the data stored in the tree.
89 talloc_set_destructor(tree
, tree_destructor
);
95 static inline trbt_node_t
*
96 trbt_parent(trbt_node_t
*node
)
101 static inline trbt_node_t
*
102 trbt_grandparent(trbt_node_t
*node
)
106 parent
=trbt_parent(node
);
108 return parent
->parent
;
113 static inline trbt_node_t
*
114 trbt_uncle(trbt_node_t
*node
)
116 trbt_node_t
*parent
, *grandparent
;
118 parent
=trbt_parent(node
);
122 grandparent
=trbt_parent(parent
);
126 if(parent
==grandparent
->left
){
127 return grandparent
->right
;
129 return grandparent
->left
;
133 static inline void trbt_insert_case1(trbt_tree_t
*tree
, trbt_node_t
*node
);
134 static inline void trbt_insert_case2(trbt_tree_t
*tree
, trbt_node_t
*node
);
137 trbt_rotate_left(trbt_node_t
*node
)
139 trbt_tree_t
*tree
= node
->tree
;
142 if(node
->parent
->left
==node
){
143 node
->parent
->left
=node
->right
;
145 node
->parent
->right
=node
->right
;
148 tree
->root
=node
->right
;
150 node
->right
->parent
=node
->parent
;
151 node
->parent
=node
->right
;
152 node
->right
=node
->right
->left
;
154 node
->right
->parent
=node
;
156 node
->parent
->left
=node
;
160 trbt_rotate_right(trbt_node_t
*node
)
162 trbt_tree_t
*tree
= node
->tree
;
165 if(node
->parent
->left
==node
){
166 node
->parent
->left
=node
->left
;
168 node
->parent
->right
=node
->left
;
171 tree
->root
=node
->left
;
173 node
->left
->parent
=node
->parent
;
174 node
->parent
=node
->left
;
175 node
->left
=node
->left
->right
;
177 node
->left
->parent
=node
;
179 node
->parent
->right
=node
;
182 /* NULL nodes are black by definition */
183 static inline int trbt_get_color(trbt_node_t
*node
)
188 return node
->rb_color
;
190 static inline int trbt_get_color_left(trbt_node_t
*node
)
195 if (node
->left
==NULL
) {
198 return node
->left
->rb_color
;
200 static inline int trbt_get_color_right(trbt_node_t
*node
)
205 if (node
->right
==NULL
) {
208 return node
->right
->rb_color
;
210 /* setting a NULL node to black is a nop */
211 static inline void trbt_set_color(trbt_node_t
*node
, int color
)
213 if ( (node
==NULL
) && (color
==TRBT_BLACK
) ) {
216 node
->rb_color
= color
;
218 static inline void trbt_set_color_left(trbt_node_t
*node
, int color
)
220 if ( ((node
==NULL
)||(node
->left
==NULL
)) && (color
==TRBT_BLACK
) ) {
223 node
->left
->rb_color
= color
;
225 static inline void trbt_set_color_right(trbt_node_t
*node
, int color
)
227 if ( ((node
==NULL
)||(node
->right
==NULL
)) && (color
==TRBT_BLACK
) ) {
230 node
->right
->rb_color
= color
;
234 trbt_insert_case5(trbt_tree_t
*tree
, trbt_node_t
*node
)
236 trbt_node_t
*grandparent
;
239 parent
=trbt_parent(node
);
240 grandparent
=trbt_parent(parent
);
241 parent
->rb_color
=TRBT_BLACK
;
242 grandparent
->rb_color
=TRBT_RED
;
243 if( (node
==parent
->left
) && (parent
==grandparent
->left
) ){
244 trbt_rotate_right(grandparent
);
246 trbt_rotate_left(grandparent
);
251 trbt_insert_case4(trbt_tree_t
*tree
, trbt_node_t
*node
)
253 trbt_node_t
*grandparent
;
256 parent
=trbt_parent(node
);
257 grandparent
=trbt_parent(parent
);
261 if( (node
==parent
->right
) && (parent
==grandparent
->left
) ){
262 trbt_rotate_left(parent
);
264 } else if( (node
==parent
->left
) && (parent
==grandparent
->right
) ){
265 trbt_rotate_right(parent
);
268 trbt_insert_case5(tree
, node
);
272 trbt_insert_case3(trbt_tree_t
*tree
, trbt_node_t
*node
)
274 trbt_node_t
*grandparent
;
278 uncle
=trbt_uncle(node
);
279 if(uncle
&& (uncle
->rb_color
==TRBT_RED
)){
280 parent
=trbt_parent(node
);
281 parent
->rb_color
=TRBT_BLACK
;
282 uncle
->rb_color
=TRBT_BLACK
;
283 grandparent
=trbt_grandparent(node
);
284 grandparent
->rb_color
=TRBT_RED
;
285 trbt_insert_case1(tree
, grandparent
);
287 trbt_insert_case4(tree
, node
);
292 trbt_insert_case2(trbt_tree_t
*tree
, trbt_node_t
*node
)
296 parent
=trbt_parent(node
);
297 /* parent is always non-NULL here */
298 if(parent
->rb_color
==TRBT_BLACK
){
301 trbt_insert_case3(tree
, node
);
305 trbt_insert_case1(trbt_tree_t
*tree
, trbt_node_t
*node
)
309 parent
=trbt_parent(node
);
311 node
->rb_color
=TRBT_BLACK
;
314 trbt_insert_case2(tree
, node
);
317 static inline trbt_node_t
*
318 trbt_sibling(trbt_node_t
*node
)
322 parent
=trbt_parent(node
);
327 if (node
== parent
->left
) {
328 return parent
->right
;
335 trbt_delete_case6(trbt_node_t
*node
)
337 trbt_node_t
*sibling
, *parent
;
339 sibling
= trbt_sibling(node
);
340 parent
= trbt_parent(node
);
342 trbt_set_color(sibling
, parent
->rb_color
);
343 trbt_set_color(parent
, TRBT_BLACK
);
344 if (node
== parent
->left
) {
345 trbt_set_color_right(sibling
, TRBT_BLACK
);
346 trbt_rotate_left(parent
);
348 trbt_set_color_left(sibling
, TRBT_BLACK
);
349 trbt_rotate_right(parent
);
355 trbt_delete_case5(trbt_node_t
*node
)
357 trbt_node_t
*parent
, *sibling
;
359 parent
= trbt_parent(node
);
360 sibling
= trbt_sibling(node
);
361 if ( (node
== parent
->left
)
362 &&(trbt_get_color(sibling
) == TRBT_BLACK
)
363 &&(trbt_get_color_left(sibling
) == TRBT_RED
)
364 &&(trbt_get_color_right(sibling
) == TRBT_BLACK
) ){
365 trbt_set_color(sibling
, TRBT_RED
);
366 trbt_set_color_left(sibling
, TRBT_BLACK
);
367 trbt_rotate_right(sibling
);
368 trbt_delete_case6(node
);
371 if ( (node
== parent
->right
)
372 &&(trbt_get_color(sibling
) == TRBT_BLACK
)
373 &&(trbt_get_color_right(sibling
) == TRBT_RED
)
374 &&(trbt_get_color_left(sibling
) == TRBT_BLACK
) ){
375 trbt_set_color(sibling
, TRBT_RED
);
376 trbt_set_color_right(sibling
, TRBT_BLACK
);
377 trbt_rotate_left(sibling
);
378 trbt_delete_case6(node
);
382 trbt_delete_case6(node
);
386 trbt_delete_case4(trbt_node_t
*node
)
388 trbt_node_t
*sibling
;
390 sibling
= trbt_sibling(node
);
391 if ( (trbt_get_color(node
->parent
) == TRBT_RED
)
392 &&(trbt_get_color(sibling
) == TRBT_BLACK
)
393 &&(trbt_get_color_left(sibling
) == TRBT_BLACK
)
394 &&(trbt_get_color_right(sibling
) == TRBT_BLACK
) ){
395 trbt_set_color(sibling
, TRBT_RED
);
396 trbt_set_color(node
->parent
, TRBT_BLACK
);
398 trbt_delete_case5(node
);
402 static void trbt_delete_case1(trbt_node_t
*node
);
405 trbt_delete_case3(trbt_node_t
*node
)
407 trbt_node_t
*sibling
;
409 sibling
= trbt_sibling(node
);
410 if ( (trbt_get_color(node
->parent
) == TRBT_BLACK
)
411 &&(trbt_get_color(sibling
) == TRBT_BLACK
)
412 &&(trbt_get_color_left(sibling
) == TRBT_BLACK
)
413 &&(trbt_get_color_right(sibling
) == TRBT_BLACK
) ){
414 trbt_set_color(sibling
, TRBT_RED
);
415 trbt_delete_case1(node
->parent
);
417 trbt_delete_case4(node
);
422 trbt_delete_case2(trbt_node_t
*node
)
424 trbt_node_t
*sibling
;
426 sibling
= trbt_sibling(node
);
427 if (trbt_get_color(sibling
) == TRBT_RED
) {
428 trbt_set_color(node
->parent
, TRBT_RED
);
429 trbt_set_color(sibling
, TRBT_BLACK
);
430 if (node
== node
->parent
->left
) {
431 trbt_rotate_left(node
->parent
);
433 trbt_rotate_right(node
->parent
);
436 trbt_delete_case3(node
);
440 trbt_delete_case1(trbt_node_t
*node
)
445 trbt_delete_case2(node
);
450 delete_node(trbt_node_t
*node
, bool from_destructor
)
452 trbt_node_t
*parent
, *child
, dc
;
453 trbt_node_t
*temp
= NULL
;
455 /* This node has two child nodes, then just copy the content
456 from the next smaller node with this node and delete the
458 The predecessor is guaranteed to have at most one child
459 node since its right arm must be NULL
460 (It must be NULL since we are its sucessor and we are above
463 if (node
->left
!= NULL
&& node
->right
!= NULL
) {
464 /* This node has two children, just copy the data */
465 /* find the predecessor */
468 while (temp
->right
!= NULL
) {
472 /* swap the predecessor data and key with the node to
475 node
->key32
= temp
->key32
;
476 node
->data
= temp
->data
;
477 /* now we let node hang off the new data */
478 talloc_steal(node
->data
, node
);
482 /* then delete the temp node.
483 this node is guaranteed to have at least one leaf
485 delete_node(temp
, from_destructor
);
490 /* There is at most one child to this node to be deleted */
496 /* If the node to be deleted did not have any child at all we
497 create a temporary dummy node for the child and mark it black.
498 Once the delete of the node is finished, we remove this dummy
499 node, which is simple to do since it is guaranteed that it will
500 still not have any children after the delete operation.
501 This is because we dont represent the leaf-nodes as actual nodes
502 in this implementation.
506 child
->tree
= node
->tree
;
509 child
->rb_color
=TRBT_BLACK
;
513 /* replace node with child */
514 parent
= trbt_parent(node
);
516 if (parent
->left
== node
) {
517 parent
->left
= child
;
519 parent
->right
= child
;
522 node
->tree
->root
= child
;
524 child
->parent
= node
->parent
;
527 if (node
->rb_color
== TRBT_BLACK
) {
528 if (trbt_get_color(child
) == TRBT_RED
) {
529 child
->rb_color
= TRBT_BLACK
;
531 trbt_delete_case1(child
);
535 /* If we had to create a temporary dummy node to represent a black
536 leaf child we now has to delete it.
537 This is simple since this dummy node originally had no children
538 and we are guaranteed that it will also not have any children
539 after the node has been deleted and any possible rotations
542 The only special case is if this was the last node of the tree
543 in which case we have to reset the root to NULL as well.
544 Othervise it is enough to just unlink the child from its new
548 if (child
->parent
== NULL
) {
549 node
->tree
->root
= NULL
;
550 } else if (child
== child
->parent
->left
) {
551 child
->parent
->left
= NULL
;
553 child
->parent
->right
= NULL
;
558 if (!from_destructor
) {
562 /* if we came from a destructor and temp!=NULL this means we
563 did the node-swap but now the tree still contains the old
564 node which was freed in the destructor. Not good.
566 if (from_destructor
&& temp
) {
567 temp
->key32
= node
->key32
;
568 temp
->rb_color
= node
->rb_color
;
570 temp
->data
= node
->data
;
571 talloc_steal(temp
->data
, temp
);
573 temp
->parent
= node
->parent
;
575 if (temp
->parent
->left
== node
) {
576 temp
->parent
->left
= temp
;
578 temp
->parent
->right
= temp
;
582 temp
->left
= node
->left
;
584 temp
->left
->parent
= temp
;
586 temp
->right
= node
->right
;
588 temp
->right
->parent
= temp
;
591 if (temp
->tree
->root
== node
) {
592 temp
->tree
->root
= temp
;
596 if ( (node
->tree
->flags
& TRBT_AUTOFREE
)
597 && (node
->tree
->root
== NULL
) ) {
598 talloc_free(node
->tree
);
605 destroy a node and remove it from its tree
607 static int node_destructor(trbt_node_t
*node
)
609 delete_node(node
, true);
614 static inline trbt_node_t
*
615 trbt_create_node(trbt_tree_t
*tree
, trbt_node_t
*parent
, uint32_t key
, void *data
)
619 node
=talloc_zero(tree
, trbt_node_t
);
620 NO_MEMORY_FATAL(node
);
623 node
->rb_color
=TRBT_BLACK
;
630 /* let this node hang off data so that it is removed when
633 talloc_steal(data
, node
);
634 talloc_set_destructor(node
, node_destructor
);
639 /* insert a new node in the tree.
640 if there is already a node with a matching key in the tree
641 we replace it with the new data and return a pointer to the old data
642 in case the caller wants to take any special action
645 trbt_insert32(trbt_tree_t
*tree
, uint32_t key
, void *data
)
651 /* is this the first node ?*/
653 node
= trbt_create_node(tree
, NULL
, key
, data
);
659 /* it was not the new root so walk the tree until we find where to
660 * insert this new leaf.
663 /* this node already exists, replace data and return the
666 if(key
==node
->key32
){
669 old_data
= node
->data
;
671 /* Let the node now be owned by the new data
672 so the node is freed when the enw data is released
674 talloc_steal(node
->data
, node
);
678 if(key
<node
->key32
) {
680 /* new node to the left */
681 trbt_node_t
*new_node
;
683 new_node
= trbt_create_node(tree
, node
, key
, data
);
692 if(key
>node
->key32
) {
694 /* new node to the right */
695 trbt_node_t
*new_node
;
697 new_node
= trbt_create_node(tree
, node
, key
, data
);
698 node
->right
=new_node
;
707 /* node will now point to the newly created node */
708 node
->rb_color
=TRBT_RED
;
709 trbt_insert_case1(tree
, node
);
714 trbt_lookup32(trbt_tree_t
*tree
, uint32_t key
)
721 if(key
==node
->key32
){
737 /* This deletes a node from the tree.
738 Note that this does not release the data that the node points to
741 trbt_delete32(trbt_tree_t
*tree
, uint32_t key
)
748 if(key
==node
->key32
){
749 delete_node(node
, false);
765 trbt_insert32_callback(trbt_tree_t
*tree
, uint32_t key
, void *(*callback
)(void *param
, void *data
), void *param
)
771 /* is this the first node ?*/
773 node
= trbt_create_node(tree
, NULL
, key
,
774 callback(param
, NULL
));
780 /* it was not the new root so walk the tree until we find where to
781 * insert this new leaf.
784 /* this node already exists, replace it
786 if(key
==node
->key32
){
787 node
->data
= callback(param
, node
->data
);
788 talloc_steal(node
->data
, node
);
792 if(key
<node
->key32
) {
794 /* new node to the left */
795 trbt_node_t
*new_node
;
797 new_node
= trbt_create_node(tree
, node
, key
,
798 callback(param
, NULL
));
807 if(key
>node
->key32
) {
809 /* new node to the right */
810 trbt_node_t
*new_node
;
812 new_node
= trbt_create_node(tree
, node
, key
,
813 callback(param
, NULL
));
814 node
->right
=new_node
;
823 /* node will now point to the newly created node */
824 node
->rb_color
=TRBT_RED
;
825 trbt_insert_case1(tree
, node
);
830 struct trbt_array_param
{
831 void *(*callback
)(void *param
, void *data
);
837 static void *array_insert_callback(void *p
, void *data
)
839 struct trbt_array_param
*param
= (struct trbt_array_param
*)p
;
840 trbt_tree_t
*tree
= NULL
;
843 /* if keylen has reached 0 we are done and can call the users
844 callback function with the users parameters
846 if (param
->keylen
== 0) {
847 return param
->callback(param
->param
, data
);
851 /* keylen is not zero yes so we must create/process more subtrees */
852 /* if data is NULL this means we did not yet have a subtree here
853 and we must create one.
856 /* create a new subtree and hang it off our current tree
857 set it to autofree so that the tree is freed when
858 the last node in it has been released.
860 tree
= trbt_create(param
->tree
, TRBT_AUTOFREE
);
862 /* we already have a subtree for this path */
863 tree
= (trbt_tree_t
*)data
;
866 trbt_insertarray32_callback(tree
, param
->keylen
, param
->key
, param
->callback
, param
->param
);
868 /* now return either the old tree we got in *data or the new tree
869 we created to our caller so he can update his pointer in his
870 tree to point to our subtree
877 /* insert into the tree using an array of uint32 as a key */
879 trbt_insertarray32_callback(trbt_tree_t
*tree
, uint32_t keylen
, uint32_t *key
, void *(*cb
)(void *param
, void *data
), void *pm
)
881 struct trbt_array_param tap
;
883 /* keylen-1 and key[1] since the call to insert32 will consume the
884 first part of the key.
888 tap
.keylen
= keylen
-1;
892 trbt_insert32_callback(tree
, key
[0], array_insert_callback
, &tap
);
895 /* lookup the tree using an array of uint32 as a key */
897 trbt_lookuparray32(trbt_tree_t
*tree
, uint32_t keylen
, uint32_t *key
)
899 /* if keylen is 1 we can do a regular lookup and return this to the
903 return trbt_lookup32(tree
, key
[0]);
906 /* we need to lookup the next subtree */
907 tree
= trbt_lookup32(tree
, key
[0]);
909 /* the key does not exist, return NULL */
913 /* now lookup the next part of the key in our new tree */
914 return trbt_lookuparray32(tree
, keylen
-1, &key
[1]);
918 /* traverse a tree starting at node */
920 trbt_traversearray32_node(trbt_node_t
*node
, uint32_t keylen
,
921 int (*callback
)(void *param
, void *data
),
924 trbt_node_t
*left
= node
->left
;
925 trbt_node_t
*right
= node
->right
;
929 ret
= trbt_traversearray32_node(left
, keylen
, callback
, param
);
935 /* this is the smallest node in this subtree
936 if keylen is 0 this means we can just call the callback
937 otherwise we must pull the next subtree and traverse that one as well
942 ret
= callback(param
, node
->data
);
949 ret
= trbt_traversearray32(node
->data
, keylen
, callback
, param
);
958 ret
= trbt_traversearray32_node(right
, keylen
, callback
, param
);
968 /* traverse the tree using an array of uint32 as a key */
970 trbt_traversearray32(trbt_tree_t
*tree
, uint32_t keylen
,
971 int (*callback
)(void *param
, void *data
),
985 return trbt_traversearray32_node(node
, keylen
-1, callback
, param
);
989 /* this function will return the first node in a tree where
990 the key is an array of uint32_t
993 trbt_findfirstarray32(trbt_tree_t
*tree
, uint32_t keylen
)
1010 while (node
->left
) {
1014 /* we found our node so return the data */
1019 /* we are still traversing subtrees so find the first node in the
1022 return trbt_findfirstarray32(node
->data
, keylen
-1);
1027 static void printtree(trbt_node_t
*node
, int levels
)
1030 if(node
==NULL
)return;
1031 printtree(node
->left
, levels
+1);
1033 for(i
=0;i
<levels
;i
++)printf(" ");
1034 printf("key:%d COLOR:%s (node:%p parent:%p left:%p right:%p)\n",node
->key32
,node
->rb_color
==TRBT_BLACK
?"BLACK":"RED", node
, node
->parent
, node
->left
, node
->right
);
1036 printtree(node
->right
, levels
+1);
1040 void print_tree(trbt_tree_t
*tree
)
1042 if(tree
->root
==NULL
){
1043 printf("tree is empty\n");
1047 printtree(tree
->root
->left
, 1);
1048 printf("root node key:%d COLOR:%s (node:%p left:%p right:%p)\n",tree
->root
->key32
,tree
->root
->rb_color
==TRBT_BLACK
?"BLACK":"RED", tree
->root
, tree
->root
->left
, tree
->root
->right
);
1049 printtree(tree
->root
->right
, 1);
1062 tree
=trbt_create(talloc_new(NULL
), 0);
1065 printf("adding node %i\n",i
);
1066 trbt_insert32(tree
, i
, NULL
);
1069 printf("deleting node %i\n",3);
1070 trbt_delete32(tree
, 3);
1073 printf("deleting node %i\n",i
);
1074 trbt_delete32(tree
, i
);
1081 printf("iteration : %d\n",cnt
);
1083 printf("adding node %i\n",i
);
1084 trbt_insert32(tree
, i
, NULL
);
1088 printf("deleting node %i\n",i
);
1089 trbt_delete32(tree
, i
);