1 /* Ordered {set,map} data type implemented by a binary tree.
2 Copyright (C) 2006-2007, 2009-2020 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2006.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* A red-black tree is a binary tree where every node is colored black or
21 2. No red node has a red parent.
22 Or equivalently: No red node has a red child.
23 3. All paths from the root down to any NULL endpoint contain the same
24 number of black nodes.
25 Let's call this the "black-height" bh of the tree. It follows that every
26 such path contains exactly bh black and between 0 and bh red nodes. (The
27 extreme cases are a path containing only black nodes, and a path colored
28 alternately black-red-black-red-...-black-red.) The height of the tree
29 therefore is >= bh, <= 2*bh.
32 /* Color of a node. */
33 typedef enum color
{ BLACK
, RED
} color_t
;
35 /* Tree node implementation, valid for this file only. */
38 struct NODE_IMPL
*left
; /* left branch, or NULL */
39 struct NODE_IMPL
*right
; /* right branch, or NULL */
40 /* Parent pointer, or NULL. The parent pointer is not needed for most
41 operations. It is needed so that a NODE_T can be returned without
42 memory allocation, on which the functions <container>_remove_node,
43 <container>_add_before, <container>_add_after can be implemented. */
44 struct NODE_IMPL
*parent
;
45 color_t color
; /* node's color */
48 typedef struct NODE_IMPL
* NODE_T
;
50 /* Concrete CONTAINER_IMPL type, valid for this file only. */
53 struct CONTAINER_IMPL_BASE base
;
54 struct NODE_IMPL
*root
; /* root node or NULL */
55 size_t count
; /* number of nodes */
58 /* A red-black tree of height h has a black-height bh >= ceil(h/2) and
59 therefore at least 2^ceil(h/2) - 1 elements. So, h <= 116 (because a tree
60 of height h >= 117 would have at least 2^59 - 1 elements, and because even
62 sizeof (NODE_IMPL) * (2^59 - 1) > 2^64
63 this would exceed the address space of the machine. */
66 /* Rotates left a subtree.
74 Changes the tree structure, updates the branch sizes.
75 The caller must update the colors and register D as child of its parent. */
77 rotate_left (NODE_T b_node
, NODE_T d_node
)
79 NODE_T c_node
= d_node
->left
;
81 b_node
->right
= c_node
;
82 d_node
->left
= b_node
;
84 d_node
->parent
= b_node
->parent
;
85 b_node
->parent
= d_node
;
87 c_node
->parent
= b_node
;
92 /* Rotates right a subtree.
100 Changes the tree structure, updates the branch sizes.
101 The caller must update the colors and register B as child of its parent. */
103 rotate_right (NODE_T b_node
, NODE_T d_node
)
105 NODE_T c_node
= b_node
->right
;
107 d_node
->left
= c_node
;
108 b_node
->right
= d_node
;
110 b_node
->parent
= d_node
->parent
;
111 d_node
->parent
= b_node
;
113 c_node
->parent
= d_node
;
118 /* Ensures the tree is balanced, after an insertion operation.
119 Also assigns node->color.
120 parent is the given node's parent, known to be non-NULL. */
122 rebalance_after_add (CONTAINER_T container
, NODE_T node
, NODE_T parent
)
126 /* At this point, parent = node->parent != NULL.
127 Think of node->color being RED (although node->color is not yet
132 if (parent
->color
== BLACK
)
134 /* A RED color for node is acceptable. */
139 grandparent
= parent
->parent
;
140 /* Since parent is RED, we know that
141 grandparent is != NULL and colored BLACK. */
143 if (grandparent
->left
== parent
)
144 uncle
= grandparent
->right
;
145 else if (grandparent
->right
== parent
)
146 uncle
= grandparent
->left
;
150 if (uncle
!= NULL
&& uncle
->color
== RED
)
152 /* Change grandparent from BLACK to RED, and
153 change parent and uncle from RED to BLACK.
154 This makes it acceptable for node to be RED. */
156 parent
->color
= uncle
->color
= BLACK
;
161 /* grandparent and uncle are BLACK. parent is RED. node wants
163 In this case, recoloring is not sufficient. Need to perform
164 one or two rotations. */
165 NODE_T
*grandparentp
;
167 if (grandparent
->parent
== NULL
)
168 grandparentp
= &container
->root
;
169 else if (grandparent
->parent
->left
== grandparent
)
170 grandparentp
= &grandparent
->parent
->left
;
171 else if (grandparent
->parent
->right
== grandparent
)
172 grandparentp
= &grandparent
->parent
->right
;
176 if (grandparent
->left
== parent
)
178 if (parent
->right
== node
)
180 /* Rotation between node and parent. */
181 grandparent
->left
= rotate_left (parent
, node
);
183 parent
= grandparent
->left
;
185 /* grandparent and uncle are BLACK. parent and node want to be
186 RED. parent = grandparent->left. node = parent->left.
191 parent uncle --> node grandparent
197 *grandparentp
= rotate_right (parent
, grandparent
);
198 parent
->color
= BLACK
;
199 node
->color
= grandparent
->color
= RED
;
201 else /* grandparent->right == parent */
203 if (parent
->left
== node
)
205 /* Rotation between node and parent. */
206 grandparent
->right
= rotate_right (node
, parent
);
208 parent
= grandparent
->right
;
210 /* grandparent and uncle are BLACK. parent and node want to be
211 RED. parent = grandparent->right. node = parent->right.
216 uncle parent --> grandparent node
222 *grandparentp
= rotate_left (grandparent
, parent
);
223 parent
->color
= BLACK
;
224 node
->color
= grandparent
->color
= RED
;
229 /* Start again with a new (node, parent) pair. */
230 parent
= node
->parent
;
234 /* Change node's color from RED to BLACK. This increases the
235 tree's black-height. */
242 /* Ensures the tree is balanced, after a deletion operation.
243 CHILD was a grandchild of PARENT and is now its child. Between them,
244 a black node was removed. CHILD is also black, or NULL.
245 (CHILD can also be NULL. But PARENT is non-NULL.) */
247 rebalance_after_remove (CONTAINER_T container
, NODE_T child
, NODE_T parent
)
251 /* At this point, we reduced the black-height of the CHILD subtree by 1.
252 To make up, either look for a possibility to turn a RED to a BLACK
253 node, or try to reduce the black-height tree of CHILD's sibling
257 if (parent
->parent
== NULL
)
258 parentp
= &container
->root
;
259 else if (parent
->parent
->left
== parent
)
260 parentp
= &parent
->parent
->left
;
261 else if (parent
->parent
->right
== parent
)
262 parentp
= &parent
->parent
->right
;
266 if (parent
->left
== child
)
268 NODE_T sibling
= parent
->right
;
269 /* sibling's black-height is >= 1. In particular,
278 if (sibling
->color
== RED
)
280 /* sibling is RED, hence parent is BLACK and sibling's children
281 are non-NULL and BLACK.
286 child sibling --> parent SR
292 *parentp
= rotate_left (parent
, sibling
);
294 sibling
->color
= BLACK
;
296 /* Concentrate on the subtree of parent. The new sibling is
297 one of the old sibling's children, and known to be BLACK. */
298 parentp
= &sibling
->left
;
299 sibling
= parent
->right
;
301 /* Now we know that sibling is BLACK.
308 if (sibling
->right
!= NULL
&& sibling
->right
->color
== RED
)
314 child sibling --> parent SR
320 *parentp
= rotate_left (parent
, sibling
);
321 sibling
->color
= parent
->color
;
322 parent
->color
= BLACK
;
323 sibling
->right
->color
= BLACK
;
326 else if (sibling
->left
!= NULL
&& sibling
->left
->color
== RED
)
332 child sibling --> child SL
341 where SLL, SLR, SR are all black.
343 parent
->right
= rotate_right (sibling
->left
, sibling
);
344 /* Change sibling from BLACK to RED and SL from RED to BLACK. */
345 sibling
->color
= RED
;
346 sibling
= parent
->right
;
347 sibling
->color
= BLACK
;
349 /* Now do as in the previous case. */
350 *parentp
= rotate_left (parent
, sibling
);
351 sibling
->color
= parent
->color
;
352 parent
->color
= BLACK
;
353 sibling
->right
->color
= BLACK
;
358 if (parent
->color
== BLACK
)
360 /* Change sibling from BLACK to RED. Then the entire
361 subtree at parent has decreased its black-height.
365 child sibling --> child sibling
368 sibling
->color
= RED
;
374 /* Change parent from RED to BLACK, but compensate by
375 changing sibling from BLACK to RED.
379 child sibling --> child sibling
382 parent
->color
= BLACK
;
383 sibling
->color
= RED
;
388 else if (parent
->right
== child
)
390 NODE_T sibling
= parent
->left
;
391 /* sibling's black-height is >= 1. In particular,
400 if (sibling
->color
== RED
)
402 /* sibling is RED, hence parent is BLACK and sibling's children
403 are non-NULL and BLACK.
408 sibling child --> SR parent
414 *parentp
= rotate_right (sibling
, parent
);
416 sibling
->color
= BLACK
;
418 /* Concentrate on the subtree of parent. The new sibling is
419 one of the old sibling's children, and known to be BLACK. */
420 parentp
= &sibling
->right
;
421 sibling
= parent
->left
;
423 /* Now we know that sibling is BLACK.
430 if (sibling
->left
!= NULL
&& sibling
->left
->color
== RED
)
436 sibling child --> SL parent
442 *parentp
= rotate_right (sibling
, parent
);
443 sibling
->color
= parent
->color
;
444 parent
->color
= BLACK
;
445 sibling
->left
->color
= BLACK
;
448 else if (sibling
->right
!= NULL
&& sibling
->right
->color
== RED
)
454 sibling child --> SR child
463 where SL, SRL, SRR are all black.
465 parent
->left
= rotate_left (sibling
, sibling
->right
);
466 /* Change sibling from BLACK to RED and SL from RED to BLACK. */
467 sibling
->color
= RED
;
468 sibling
= parent
->left
;
469 sibling
->color
= BLACK
;
471 /* Now do as in the previous case. */
472 *parentp
= rotate_right (sibling
, parent
);
473 sibling
->color
= parent
->color
;
474 parent
->color
= BLACK
;
475 sibling
->left
->color
= BLACK
;
480 if (parent
->color
== BLACK
)
482 /* Change sibling from BLACK to RED. Then the entire
483 subtree at parent has decreased its black-height.
487 sibling child --> sibling child
490 sibling
->color
= RED
;
496 /* Change parent from RED to BLACK, but compensate by
497 changing sibling from BLACK to RED.
501 sibling child --> sibling child
504 parent
->color
= BLACK
;
505 sibling
->color
= RED
;
513 /* Start again with a new (child, parent) pair. */
514 parent
= child
->parent
;
516 #if 0 /* Already handled. */
517 if (child
!= NULL
&& child
->color
== RED
)
519 child
->color
= BLACK
;
530 gl_tree_nx_add_first (CONTAINER_T container
, NODE_PAYLOAD_PARAMS
)
532 /* Create new node. */
534 (struct NODE_IMPL
*) malloc (sizeof (struct NODE_IMPL
));
536 if (new_node
== NULL
)
539 new_node
->left
= NULL
;
540 new_node
->right
= NULL
;
541 NODE_PAYLOAD_ASSIGN(new_node
)
543 /* Add it to the tree. */
544 if (container
->root
== NULL
)
546 new_node
->color
= BLACK
;
547 container
->root
= new_node
;
548 new_node
->parent
= NULL
;
554 for (node
= container
->root
; node
->left
!= NULL
; )
557 node
->left
= new_node
;
558 new_node
->parent
= node
;
560 /* Color and rebalance. */
561 rebalance_after_add (container
, new_node
, node
);
568 /* Adds the already allocated NEW_NODE to the tree, right before NODE. */
570 gl_tree_add_node_before (CONTAINER_T container
, NODE_T node
, NODE_T new_node
)
572 new_node
->left
= NULL
;
573 new_node
->right
= NULL
;
575 /* Add it to the tree. */
576 if (node
->left
== NULL
)
577 node
->left
= new_node
;
580 for (node
= node
->left
; node
->right
!= NULL
; )
582 node
->right
= new_node
;
584 new_node
->parent
= node
;
586 /* Color and rebalance. */
587 rebalance_after_add (container
, new_node
, node
);
593 gl_tree_nx_add_before (CONTAINER_T container
, NODE_T node
, NODE_PAYLOAD_PARAMS
)
595 /* Create new node. */
597 (struct NODE_IMPL
*) malloc (sizeof (struct NODE_IMPL
));
599 if (new_node
== NULL
)
602 NODE_PAYLOAD_ASSIGN(new_node
)
604 gl_tree_add_node_before (container
, node
, new_node
);
608 /* Adds the already allocated NEW_NODE to the tree, right after NODE. */
610 gl_tree_add_node_after (CONTAINER_T container
, NODE_T node
, NODE_T new_node
)
612 new_node
->left
= NULL
;
613 new_node
->right
= NULL
;
615 /* Add it to the tree. */
616 if (node
->right
== NULL
)
617 node
->right
= new_node
;
620 for (node
= node
->right
; node
->left
!= NULL
; )
622 node
->left
= new_node
;
624 new_node
->parent
= node
;
626 /* Color and rebalance. */
627 rebalance_after_add (container
, new_node
, node
);
633 gl_tree_nx_add_after (CONTAINER_T container
, NODE_T node
, NODE_PAYLOAD_PARAMS
)
635 /* Create new node. */
637 (struct NODE_IMPL
*) malloc (sizeof (struct NODE_IMPL
));
639 if (new_node
== NULL
)
642 NODE_PAYLOAD_ASSIGN(new_node
)
644 gl_tree_add_node_after (container
, node
, new_node
);
649 gl_tree_remove_node_no_free (CONTAINER_T container
, NODE_T node
)
651 NODE_T parent
= node
->parent
;
653 if (node
->left
== NULL
)
655 /* Replace node with node->right. */
656 NODE_T child
= node
->right
;
660 child
->parent
= parent
;
661 /* Since node->left == NULL, child must be RED and of height 1,
662 hence node must have been BLACK. Recolor the child. */
663 child
->color
= BLACK
;
666 container
->root
= child
;
669 if (parent
->left
== node
)
670 parent
->left
= child
;
671 else /* parent->right == node */
672 parent
->right
= child
;
674 if (child
== NULL
&& node
->color
== BLACK
)
675 rebalance_after_remove (container
, child
, parent
);
678 else if (node
->right
== NULL
)
680 /* It is not absolutely necessary to treat this case. But the more
681 general case below is more complicated, hence slower. */
682 /* Replace node with node->left. */
683 NODE_T child
= node
->left
;
685 child
->parent
= parent
;
686 /* Since node->right == NULL, child must be RED and of height 1,
687 hence node must have been BLACK. Recolor the child. */
688 child
->color
= BLACK
;
690 container
->root
= child
;
693 if (parent
->left
== node
)
694 parent
->left
= child
;
695 else /* parent->right == node */
696 parent
->right
= child
;
701 /* Replace node with the rightmost element of the node->left subtree. */
705 color_t removed_color
;
707 for (subst
= node
->left
; subst
->right
!= NULL
; )
708 subst
= subst
->right
;
710 subst_parent
= subst
->parent
;
714 removed_color
= subst
->color
;
716 /* The case subst_parent == node is special: If we do nothing special,
717 we get confusion about node->left, subst->left and child->parent.
719 <==> The 'for' loop above terminated immediately.
720 <==> subst == subst_parent->left
721 [otherwise subst == subst_parent->right]
722 In this case, we would need to first set
723 child->parent = node; node->left = child;
724 and later - when we copy subst into node's position - again
725 child->parent = subst; subst->left = child;
726 Altogether a no-op. */
727 if (subst_parent
!= node
)
730 child
->parent
= subst_parent
;
731 subst_parent
->right
= child
;
734 /* Copy subst into node's position.
735 (This is safer than to copy subst's value into node, keep node in
736 place, and free subst.) */
737 if (subst_parent
!= node
)
739 subst
->left
= node
->left
;
740 subst
->left
->parent
= subst
;
742 subst
->right
= node
->right
;
743 subst
->right
->parent
= subst
;
744 subst
->color
= node
->color
;
745 subst
->parent
= parent
;
747 container
->root
= subst
;
748 else if (parent
->left
== node
)
749 parent
->left
= subst
;
750 else /* parent->right == node */
751 parent
->right
= subst
;
753 if (removed_color
== BLACK
)
755 if (child
!= NULL
&& child
->color
== RED
)
756 /* Recolor the child. */
757 child
->color
= BLACK
;
759 /* Rebalancing starts at child's parent, that is subst_parent -
760 except when subst_parent == node. In this case, we need to use
761 its replacement, subst. */
762 rebalance_after_remove (container
, child
,
763 subst_parent
!= node
? subst_parent
: subst
);
771 gl_tree_remove_node (CONTAINER_T container
, NODE_T node
)
773 gl_tree_remove_node_no_free (container
, node
);
774 NODE_PAYLOAD_DISPOSE (container
, node
)
781 check_invariants (NODE_T node
, NODE_T parent
, size_t *counterp
)
783 unsigned int left_blackheight
=
784 (node
->left
!= NULL
? check_invariants (node
->left
, node
, counterp
) : 0);
785 unsigned int right_blackheight
=
786 (node
->right
!= NULL
? check_invariants (node
->right
, node
, counterp
) : 0);
788 if (!(node
->parent
== parent
))
790 if (!(node
->color
== BLACK
|| node
->color
== RED
))
792 if (parent
== NULL
&& !(node
->color
== BLACK
))
794 if (!(left_blackheight
== right_blackheight
))
799 return left_blackheight
+ (node
->color
== BLACK
? 1 : 0);