7 /* --- @check_recurse@ --- *
9 * Arguments: @struct bstree_nodecls *cls@ = node class for the tree
10 * @struct bstnode *const *root@ = the tree we're checking
11 * @const struct rbnode *parent@ = the node's parent, or null if
12 * we're looking at the root node
13 * @const struct rbnode *lbound, *rbound@ = left and right bound
14 * nodes, i.e., the closest ancestors from which the
15 * current node can be reached by following a right or
16 * left link, respectively; one or other of these is
18 * @const struct rbnode *node@ = the node we're looking at now,
20 * @int blkht@ = the number of black nodes on the path to the
21 * current node -- but not including it
22 * @int *tree_blkht_inout@ = address of the reference black-
23 * height for the tree, since this ought to be the same
24 * for all paths to the leaves; this is initially %$-1$%
25 * if no expected height was passed to @rbtree_check@
26 * @void *arg@ = argument to pass to check function
28 * Returns: Zero if everything was OK, %$-1$% if problems were found and
31 * Use: Recursively examine a subtree of a red-black tree, checking
32 * that it satisfies all of the necessary invariants.
35 static int check_recurse(struct bstree_nodecls *cls,
36 struct bstnode *const *root,
37 const struct rbnode *parent,
38 const struct rbnode *lbound,
39 const struct rbnode *rbound,
40 const struct rbnode *node,
41 int blkht, int *tree_blkht_inout,
44 bstree_idfn *idfn = cls->ops->id;
45 bstree_chkfn *chkfn = cls->ops->chk;
49 /* We've fallen off the bottom of the tree. */
51 /* The black-height of the tree should be the same for every path from
52 * root to leaf. If we've not previously established the black height
53 * for this tree, then we do this now. Otherwise, check that we get the
54 * same answer as last time.
56 if (*tree_blkht_inout == -1)
57 *tree_blkht_inout = blkht;
58 else if (*tree_blkht_inout != blkht) {
59 fprintf(stderr, "RBTREE %p BUG: ", (void *)root);
60 if (!parent) fputs("empty tree", stderr);
62 fputs("leaf node ", stderr);
63 if (cls->ops->id) cls->ops->id(cls, &parent->_bst, stderr);
64 else fprintf(stderr, "%p", (void*)parent);
66 fprintf(stderr, " black-height %d /= %d\n", blkht, *tree_blkht_inout);
70 /* Check that the user is happy with this leaf. */
73 parent ? &parent->_bst : 0,
74 lbound ? &lbound->_bst : 0,
75 rbound ? &rbound->_bst : 0,
76 node ? &node->_bst : 0, BSTCHK_LEAF,
80 /* We have a valid node. */
82 /* If the node is black, then increment the black-height here. (Recall
83 * that the argument doesn't include this node.) If the node is red,
84 * then check that our parent wasn't also red -- and that we're not at
87 if (!(node->f&RBF_RED))
90 fprintf(stderr, "RBTREE %p BUG: root ", (void *)root);
91 if (idfn) idfn(cls, &node->_bst, stderr);
92 else fprintf(stderr, "%p", (void*)node);
93 fputs(" is red\n", stderr);
95 } else if (parent->f&RBF_RED) {
96 fprintf(stderr, "RBTREE %p BUG: red node ", (void *)root);
97 if (idfn) idfn(cls, &node->_bst, stderr);
98 else fprintf(stderr, "%p", (void*)node);
99 fputs(" has red parent ", stderr);
100 if (idfn) idfn(cls, &parent->_bst, stderr);
101 else fprintf(stderr, "%p", (void*)parent);
106 /* Check the subtrees recursively. */
109 parent ? &parent->_bst : 0,
110 lbound ? &lbound->_bst : 0,
111 rbound ? &rbound->_bst : 0,
112 node ? &node->_bst : 0, BSTCHK_BEFORE,
115 if (check_recurse(cls, root, node, lbound, node,
116 (const struct rbnode *)node->_bst.left,
117 blkht, tree_blkht_inout, arg))
121 parent ? &parent->_bst : 0,
122 lbound ? &lbound->_bst : 0,
123 rbound ? &rbound->_bst : 0,
124 node ? &node->_bst : 0, BSTCHK_MID,
127 if (check_recurse(cls, root, node, node, rbound,
128 (const struct rbnode *)node->_bst.right,
129 blkht, tree_blkht_inout, arg))
133 parent ? &parent->_bst : 0,
134 lbound ? &lbound->_bst : 0,
135 rbound ? &rbound->_bst : 0,
136 node ? &node->_bst : 0, BSTCHK_AFTER,
145 /* --- @rbtree_check@ --- *
147 * Arguments: @struct bstree_nodecls *cls@ = node class for the tree
148 * @struct rbnode *const *root@ = root pointer that we're
150 * @int blkht@ = expected black-height for tree, or %$-1$% if
152 * @void *arg@ = argument to pass to check function
154 * Returns: Zero if everything was OK, %$-1$% if problems were found and
157 * Use: Recursively examine a red-black tree, checking that it
158 * satisfies all of the necessary invariants.
161 int rbtree_check(struct bstree_nodecls *cls,
162 struct bstnode *const *root, int blkht, void *arg)
164 return (check_recurse(cls, root, 0, 0, 0,
165 (const struct rbnode *)*root,
169 /* --- @rbtree_height@ --- *
171 * Arguments: @const struct rbnode *node@ = pointer to a tree node
173 * Returns: The `black height' for the (sub)tree rooted at @node@. This
174 * is primarily useful as input to @rbtree_join@ and
178 int rbtree_height(const struct rbnode *node)
183 if (!(node->f&RBF_RED)) blkht++;
184 node = (const struct rbnode *)node->_bst.left;
189 /* --- @rbtree_lookup@ --- *
191 * Arguments: @struct bstree_nodecls *cls@ = node class for the tree
192 * @struct bstnode *root@ = pointer to root node
193 * @void *arg@ = argument to the navigation function
195 * Returns: Pointer to the matching node, or null if it couldn't be
198 * Use: Search for a node within the tree according to the navigation
202 void *rbtree_lookup(struct bstree_nodecls *cls,
203 struct bstnode *root, void *arg)
204 { return (bstree_lookup(cls, root, arg)); }
206 /* --- @rbtree_probe@ --- *
208 * Arguments: @struct bstree_nodecls *cls@ = node class for the tree
209 * @struct bstnode **root@ = pointer to root link
210 * @const void *search_key@ = the key to search for
211 * @struct rbpath *path@ = path to fill in
213 * Returns: Pointer to the matching node, or null if it couldn't be
216 * Use: Search for a node within the tree according to the navigation
217 * function, recording the search path This can be used later,
218 * e.g., by @rbtree_insert@ to insert a new node if none was
219 * found, or by @rbtree_remove@ to remove the node that was
223 void *rbtree_probe(struct bstree_nodecls *cls,
224 struct bstnode **root, void *arg, struct rbpath *path)
225 { return (bstree_probe(cls, root, arg, path->p, &path->k)); }
227 /* --- @rbtree_inititer@ --- *
229 * Arguments: @struct bstnode *root@ = pointer to the tree header
230 * @struct rbiter *it@ = pointer to iterator to initialize
234 * Use: Initialize an iterator.
237 void rbtree_inititer(struct bstnode *root, struct rbiter *it)
238 { bstree_inititer(root, it->stack, &it->sp); }
240 /* --- @rbtree_next@ --- *
242 * Arguments: @struct rbiter *it@ = pointer to iterator
244 * Returns: A pointer to the next node in ascending order, or null
245 * if no more nodes remain.
247 * Use: Advances a tree iterator. Inserting or removing elements
248 * invalidates the iterator. As a special exception, it is
249 * permitted to free all of the nodes by iterating over the tree
250 * in the obvious manner:
252 * @rbtree_inititer(tree, &it);@
254 * @node = rbtree_next(&it); if (!node) break;@
258 * At this point, the tree header structure is left in an
259 * invalid state, and must not be used; it is, however, safe to
260 * discard, since it holds no resources.
263 void *rbtree_next(struct rbiter *it)
264 { return ((struct rbnode *)bstree_next(it->stack, &it->sp)); }
266 /* --- @rbtree_firstpath@, @rbtree_lastpath@ --- *
268 * Arguments: @struct bstnode **root@ = address of the tree root link
269 * @struct rbpath *path@ = path to fill in
271 * Returns: Pointer to the requested node, or null if the tree is empty.
273 * Use: Return the first or last node in the tree, as ordered by
274 * their keys, together with a path to the requested node, which
275 * can be used to remove them, or to navigate to other nodes in
279 void *rbtree_firstpath(struct bstnode **root, struct rbpath *path)
280 { return (bstree_firstpath(root, path->p, &path->k)); }
282 void *rbtree_lastpath(struct bstnode **root, struct rbpath *path)
283 { return (bstree_lastpath(root, path->p, &path->k)); }
285 /* --- @rbtree_nextpath@, @rbtree_prevpath@ --- *
287 * Arguments: @struct rbpath *path@ = path to update
289 * Returns: Pointer to the requested node, or null if the tree is empty
290 * or the path is already positioned at the relevant extreme.
292 * Use: Return the next or previous node in the tree, as ordered by
293 * their keys, together with a path to the requested node, which
294 * can be used to remove them, or to navigate to other nodes in
297 * If the path is full, i.e., refers to an existing node, then
298 * the functions return that node's successor or predecessor.
299 * If the path is empty, i.e., refers to a space between nodes
300 * where a new node can be inserted, then the functions return
301 * the node at the upper or lower end of the gap, unless the
302 * `gap' is actually at an extreme of the tree and no such node
303 * exists. In the latter case, a null pointer is returned.
304 * The path is modified to refer to the new node, if any, or to
305 * the gap at the appropriate extreme of the tree.
308 void *rbtree_nextpath(struct rbpath *path)
309 { return (bstree_nextpath(path->p, &path->k)); }
311 void *rbtree_prevpath(struct rbpath *path)
312 { return (bstree_prevpath(path->p, &path->k)); }
314 /* --- @rbtree_beforepath@, @rbtree_afterpath@ --- *
316 * Arguments: @struct rbpath *path@ = path to update
320 * Use: Advance the path to just before or after the current node.
321 * The path thereby becomes empty, suitable to insert an element
322 * or split the tree just before or after the previously
326 void rbtree_afterpath(struct rbpath *path)
327 { bstree_afterpath(path->p, &path->k); }
329 void rbtree_beforepath(struct rbpath *path)
330 { bstree_beforepath(path->p, &path->k); }
332 /* --- @rbtree_replace@ --- *
334 * Arguments: @struct rbpath *path@ = pointer to a full path
335 * @struct rbnode *node@ = pointer to replacement node
339 * Use: Replace the node identified by the @path@ with the given
340 * @node@. The replacement @node@ should have the same (equal,
341 * according to the node-class comparison function) key as the
342 * node it replaces, and %%\emph{must}%% be strictly between the
343 * keys of the old node's predecessor and successor. The node's
344 * links need not be initialized. Paths and iterators are not
348 void rbtree_replace(struct rbpath *path, struct rbnode *node)
350 struct rbnode *old_node;
353 old_node = (struct rbnode *)*path->p[k]; assert(old_node);
355 node->_bst = old_node->_bst;
356 node->f = (node->f&~RBF_RED) | (old_node->f&RBF_RED);
359 /* --- @rbtree_insert@ --- *
361 * Arguments: @struct bstree_nodecls *cls@ = node class for the tree
362 * @struct rbpath *path@ = pointer to an empty path
363 * @struct rbnode *node@ = the new node to add
365 * Returns: Adjustment (%$0$% or %$+1$%) to the tree black-height.
367 * Use: Add a new node to the tree, in the place determined by the
368 * empty path. The @new_node@'s key must be equal to the key
369 * passed to @rbtree_probe@ when it produced the path.
371 * The new node is not copied, and its storage must remain valid
372 * until the node is removed or the tree is discarded.
375 int rbtree_insert(struct bstree_nodecls *cls,
376 struct rbpath *path, struct rbnode *node)
378 struct rbnode *p, *n, *c, *l, *r;
379 struct bstnode **clink, **nlink, **plink;
380 bstree_updfn *updfn = cls->ops->upd;
383 /* Check that the path is well-formed and describes a failed probe. */
384 clink = path->p[k]; assert(!*clink);
386 /* Initialize the new node's links and hook it onto the tree. */
387 node->_bst.left = node->_bst.right = 0; *clink = &node->_bst;
389 /* If the tree was empty then the new node is going to be the root of the
390 * tree, which must be black.
394 if (updfn) updfn(cls, &node->_bst);
398 /* Otherwise we'll provisionally paint the new node red and try to fix
401 c = node; c->f |= RBF_RED;
403 /* The child node %$c$% is known to be red. Our focus node %$n$% is the
404 * child's parent, and it might also be red; this is the only violation
405 * of the tree invariants, and we're trying to fix it. In particular,
406 * %$c$%'s children, if any, are black. Neither %$c$% nor %$n$% has been
407 * updated yet. We'll also be interested in the focus node's parent
408 * %$p$%. The focus node's sibling, denoted %$s$% in the diagrams below,
409 * is also interesting to the theory, but not named explicitly in the
413 /* Retrieve the focus node, which must exist because %$c$% is red and the
414 * tree root is black. If the focus node is black then we're done.
416 nlink = path->p[--k]; n = (struct rbnode *)*nlink;
417 if (!(n->f&RBF_RED)) {
418 if (updfn) { updfn(cls, &c->_bst); updfn(cls, &n->_bst); }
422 /* Retrieve the focus node's parent %$p$%, which must also exist for the
423 * same reason. Note that %$p$% is definitely black, since it has at
424 * least one red child.
426 plink = path->p[--k]; p = (struct rbnode *)*plink;
428 /* If the parent has two children and they're both red, then blacken them
429 * both. (This approach avoids dealing with all of the symmetry in the
430 * loop.) If the parent is the root then we're done, and the tree black-
431 * height has increased by one; otherwise, redden it and ascend.
436 * ( ) ( ) ---> (*) (*)
437 * c / \ / \ c / \ / \
441 l = (struct rbnode *)p->_bst.left; r = (struct rbnode *)p->_bst.right;
442 if (l && r && (l->f&r->f&RBF_RED)) {
443 V( fprintf(stderr, "RBTREE INSERT red sibling: %s\n",
444 k ? "ascend" : "extend tree"); )
445 l->f &= ~RBF_RED; r->f &= ~RBF_RED;
448 updfn(cls, &c->_bst); updfn(cls, &n->_bst);
449 updfn(cls, &p->_bst);
453 if (updfn) { updfn(cls, &c->_bst); updfn(cls, &n->_bst); }
454 p->f |= RBF_RED; c = p; clink = plink; continue;
457 /* Otherwise, we have some links to rewrite. */
458 if (nlink == &p->_bst.left)
459 #define FIXUP_INSERT(left, l, right, r) do { \
460 /* The focus node is its parent's left child. There are two \
461 * cases, depending on whether %$c$% is the focus node's left or \
462 * right child. It's safe to redden %$p$% here: if the focus \
463 * node has a red sibling then we'd have ascended the tree above. \
466 if (clink == &n->_bst.left) { \
476 V( fputs("RBTREE INSERT zig-zig (" #left " child)\n", stderr); ) \
477 p->_bst.left = n->_bst.right; n->_bst.right = &p->_bst; \
478 n->f &= ~RBF_RED; p->f |= RBF_RED; \
480 updfn(cls, &c->_bst); updfn(cls, &p->_bst); \
481 updfn(cls, &n->_bst); \
494 V( fputs("RBTREE INSERT zig-zag (" #left " child)\n", stderr); ) \
495 n->_bst.right = c->_bst.left; c->_bst.left = &n->_bst; \
496 p->_bst.left = c->_bst.right; c->_bst.right = &p->_bst; \
497 c->f &= ~RBF_RED; p->f |= RBF_RED; \
499 updfn(cls, &n->_bst); updfn(cls, &p->_bst); \
500 updfn(cls, &c->_bst); \
505 FIXUP_INSERT(left, l, right, r);
507 FIXUP_INSERT(right, r, left, l);
510 /* Whatever happened above, we're now done: the parent is still black. */
514 /* Follow the rest of the path up to the root, updating the nodes. */
515 if (updfn) while (k) updfn(cls, *path->p[--k]);
517 /* We're done. The overall black-height only changes if we reach the root,
518 * and we'd have returned already if that happened.
523 /* --- @rbtree_remove@ --- *
525 * Arguments: @struct bstree_nodecls *cls@ = node class for the tree
526 * @struct rbpath *path@ = pointer to a full path
528 * Returns: Adjustment (%$0$% or %$-1$%) to the tree black-height.
530 * Use: Removes the node identified by the path. The node was
531 * allocated by the caller, and should be freed by the caller in
532 * whatever way is appropriate.
535 int rbtree_remove(struct bstree_nodecls *cls, struct rbpath *path)
537 struct rbnode *n, *p, *s, *t, *l, *r;
538 struct bstnode *del, *subst, *replace, **nlink, **plink;
539 bstree_updfn *updfn = cls->ops->upd;
543 /* Unlink the node from the tree. */
544 bstree_remove(&del, &subst, &replace, path->p, &path->k);
545 t = (struct rbnode *)del; f = t->f;
546 s = (struct rbnode *)subst;
547 n = (struct rbnode *)replace;
550 /* If the node was substituted, then fix up the colouring. */
551 if (s) { ff = f; f = s->f; s->f = (f&~RBF_RED) | (ff&RBF_RED); }
553 /* We've cut out out a node %$t$%, and replaced it with one of its
554 * `children' %$n$% -- which might, in fact, be null. If %$t$% was black,
555 * then, to maintain the invariant, we (mentally) assign an additional dose
556 * of blackness to %$n$%. Our task will be to take one of these blackness
557 * doses and move it somewhere safe -- either a red ancestor, or the root,
558 * where we can just safely forget about it.
561 /* If the node we've cut out was actually red then we can just forget
565 if (updfn && n) updfn(cls, &n->_bst);
566 } else if (n && (n->f&RBF_RED)) {
567 /* If %$n$% is actually a real node, and it's red, then we can just
572 if (updfn && n) updfn(cls, &n->_bst);
574 /* It looks like we have some actual work to do. */
578 /* The node %$n$% is doubly black, and we must offload one of the doses
579 * of blackness somewhere else.
583 /* The node we're looking at is, in fact, the root. The extra
584 * blackness affects all paths to the leaves equally, so we can can
585 * just throw it away without anyone noticing, except that the tree
586 * black-height has decreased.
589 V( fputs("RBTREE REMOVE shorten tree\n", stderr); )
593 /* Not the root, so we can find a parent node. */
594 plink = path->p[--k]; p = (struct rbnode *)*plink;
596 /* In fact, because we have at least one blackness dose, we must have a
597 * live sibling, with a subtree containing at least one black node.
598 * Split into two main cases according to whether we're on the left or
601 if (nlink == &p->_bst.left)
602 #define FIXUP_REMOVE(left, l, right, r) do { \
603 /* We're the left child. */ \
605 s = (struct rbnode *)p->_bst.right; \
606 if (s->f&RBF_RED) { \
607 /* Our sibling is red. The parent must then be black, and \
608 * the sibling must have two black children, our node's \
609 * niblings, though we're only interested in the left-hand \
610 * one, which we call %$t$%. \
613 t = (struct rbnode *)s->_bst.left; \
614 l = (struct rbnode *)t->_bst.left; \
615 r = (struct rbnode *)t->_bst.right; \
617 if (r && r->f&RBF_RED) { \
618 /* The left nibling has a red right child. The following \
619 * rearrangement discharges the surplus black dose. \
624 * (* *) ( ) ---> ( ) \
625 * / \ t / \ p / \ r \
632 V( fputs("RBTREE REMOVE red sibling, " \
633 "outer red great-nibling (" #left " child)\n", \
635 p->_bst.right = l ? &l->_bst : 0; \
636 t->_bst.left = &p->_bst; s->_bst.left = &t->_bst; \
637 s->f &= ~RBF_RED; t->f |= RBF_RED; r->f &= ~RBF_RED; \
639 updfn(cls, &p->_bst); updfn(cls, &t->_bst); \
640 updfn(cls, &s->_bst); \
642 } else if (l && l->f&RBF_RED) { \
643 /* The left nibling has a red left child. The following \
644 * rearrangement discharges the surplus black dose. \
649 * (* *) ( ) ---> ( ) \
650 * / \ t / \ p / \ t \
657 V( fputs("RBTREE REMOVE red sibling, " \
658 "inner red great-nibling (" #left " child)\n", \
660 p->_bst.right = l->_bst.left; l->_bst.left = &p->_bst; \
661 t->_bst.left = l->_bst.right; l->_bst.right = &t->_bst; \
662 s->_bst.left = &l->_bst; s->f &= ~RBF_RED; \
664 updfn(cls, &p->_bst); updfn(cls, &t->_bst); \
665 updfn(cls, &l->_bst); updfn(cls, &s->_bst); \
668 /* The left nibling has no red children. The following \
669 * rearrangement discharges the surplus black dose: \
670 * reddening %$t$% is safe because it has no red children. \
675 * (* *) ( ) ---> (*) \
676 * / \ t / \ n / \ t \
681 V( fputs("RBTREE REMOVE red sibling, " \
682 "no red great-nibling (" #left " child)\n", \
684 p->_bst.right = &t->_bst; s->_bst.left = &p->_bst; \
685 s->f &= ~RBF_RED; t->f |= RBF_RED; \
686 if (updfn) { updfn(cls, &p->_bst); updfn(cls, &s->_bst); } \
689 /* Adjust the parent link. In all cases, the invariant has \
690 * been properly restored. \
692 *plink = &s->_bst; goto update; \
694 /* Our sibling is black. We can't deduce the colour of the \
698 l = (struct rbnode *)s->_bst.left; \
699 r = (struct rbnode *)s->_bst.right; \
701 if (r && r->f&RBF_RED) { \
702 /* The sibling has a red right child. The following \
703 * rearrangement discharges the surplus black dose. \
708 * (* *) (*) ---> (*) (*) \
709 * / \ / \ r n / \ / \ \
714 V( fputs("RBTREE REMOVE black sibling, " \
715 "outer red nibling (" #left " child)\n", \
717 p->_bst.right = l ? &l->_bst : 0; s->_bst.left = &p->_bst; \
718 s->f |= p->f&RBF_RED; p->f &= ~RBF_RED; r->f &= ~RBF_RED; \
719 if (updfn) { updfn(cls, &p->_bst); updfn(cls, &s->_bst); } \
720 *plink = &s->_bst; goto update; \
721 } else if (l && l->f&RBF_RED) { \
722 /* The sibling has a red left child. The following \
723 * rearrangement discharges the surplus black dose. \
728 * (* *) (*) ---> (*) (*) \
729 * / \ l / \ n / \ / \ \
734 V( fputs("RBTREE REMOVE black sibling, " \
735 "inner red nibling (" #left " child)\n", \
737 p->_bst.right = l->_bst.left; l->_bst.left = &p->_bst; \
738 s->_bst.left = l->_bst.right; l->_bst.right = &s->_bst; \
739 l->f &= ~RBF_RED | (p->f&RBF_RED); p->f &= ~RBF_RED; \
741 updfn(cls, &p->_bst); updfn(cls, &s->_bst); \
742 updfn(cls, &l->_bst); \
744 *plink = &l->_bst; goto update; \
746 /* The sibling has no red children. That means that it's \
747 * safe to make it red, so we can push the extra black \
748 * dose up into the parent. If the parent was previously \
749 * red, then we're done; otherwise, we ascend the tree. \
754 * (* *) (*) ---> (*) ( ) \
758 V( fprintf(stderr, "RBTREE REMOVE black sibling, " \
759 "%s parent, no red nibling (" #left " child)\n", \
760 p->f&RBF_RED ? "red" : "black"); ) \
762 if (updfn) updfn(cls, &p->_bst); \
763 if (p->f&RBF_RED) { p->f &= ~RBF_RED; goto update; } \
764 n = p; nlink = plink; \
768 FIXUP_REMOVE(left, l, right, r);
770 FIXUP_REMOVE(right, r, left, l);
775 /* Follow the rest of the path up to the root, updating the nodes. */
777 if (updfn) while (k) updfn(cls, *path->p[--k]);
781 /* --- @rbtree_join@ --- *
783 * Arguments: @struct bstree_nodecls *cls@ = node class for the tree
784 * @struct bstnode **root_out@ = address to store the link to
785 * the root of the combined tree
786 * @struct bstnode **left@ = address containing the current
787 * root of the left tree
788 * @int lht@ = black-height of the left tree, or %$-1$% if
790 * @struct bstnode *mid@ = pointer to middle node, or null
791 * @struct bstnode **right@ = address containing the current
792 * root of the right tree
793 * @int rht@ = black-height of the right tree, or %$-1$% if
796 * Returns: The black-height of the combined tree.
798 * Use: Concatenate two trees.
800 * Every node in the left tree must have a key strictly less
801 * than any node of the right tree. If a middle node is
802 * provided, then its key must be greater than that of any node
803 * in the left tree, and less than that of any node in the right
806 * The output is a single tree containing every node in the left
807 * and right input trees, together with the middle node, if that
810 * The @root_out@ pointer may etestqual either @left@ or @right@
811 * (or, indeed, both, only if both are empty). If @left@ is
812 * distinct from @root_out@ then @*left@ set null on exit;
813 * similarly, if @right@ is distinct from @root_out@, then
814 * @*right@ is set null on exit.
817 int rbtree_join(struct bstree_nodecls *cls,
818 struct bstnode **root_out,
819 struct bstnode **left, int lht,
821 struct bstnode **right, int rht)
823 struct rbnode *m = (struct rbnode *)mid, *p, *n, *s;
824 struct bstnode **clink, **plink, *root;
825 bstree_updfn *updfn = cls->ops->upd;
829 /* Determine the heights of the left and right trees if the caller didn't
832 if (lht < 0) lht = rbtree_height((struct rbnode *)*left);
833 if (rht < 0) rht = rbtree_height((struct rbnode *)*right);
835 /* If we're not given a joining node then take one from the right tree. If
836 * the right tree is empty, then the join is just the left tree and there's
840 if (!rht) { root = *left; blkht = lht; goto end; }
841 else if (!lht) { root = *right; blkht = rht; goto end; }
843 m = rbtree_firstpath(right, &path);
844 rht += rbtree_remove(cls, &path);
849 /* The trees have the same black-height. We can just join them the
850 * stupid way. The joining node will be the root, so it must be black,
851 * and the resulting height is one greater than the input heights.
854 V( fputs("RBTREE JOIN equal heights\n", stderr); )
855 m->_bst.left = *left; m->_bst.right = *right;
857 if (updfn) updfn(cls, &m->_bst);
858 root = &m->_bst; blkht = lht + 1;
861 #define FIXUP_JOIN(left, lht, right, rht) do { \
862 /* The left tree is taller. */ \
864 /* Find the rightmost subtree in the left tree whose black- \
865 * height is equal to the right tree's black-height. \
867 path.k = 0; path.p[0] = clink = left; blkht = lht; \
869 n = (struct rbnode *)*clink; \
870 if (!(n && (n->f&RBF_RED))) { \
871 if (blkht == rht) break; \
874 path.p[++path.k] = clink = &n->_bst.right; \
877 /* Replace this subtree with the two trees, joined by a red \
878 * node. This will preserve the global black-height invariant, \
879 * but may result in two adjacent red nodes. \
881 *clink = &m->_bst; m->f |= RBF_RED; \
882 m->_bst.left = n ? &n->_bst : 0; \
883 m->_bst.right = *right; \
884 if (updfn) updfn(cls, &m->_bst); \
886 /* Fix up the tree to restore the invariant. This is a simpler \
887 * version of the fix-up in @rbtree_insert@ above. We get to \
888 * throw out a lot of the complexity because we know that our \
889 * path runs down the extremity of the taller tree, so, in \
890 * particular, we won't need to check which side a node is from \
896 /* Fetch the parent: our child node is red, so it must have \
897 * one. If the parent is black then we're done. \
899 n = (struct rbnode *)*path.p[--path.k]; \
900 if (!(n->f&RBF_RED)) { \
901 if (updfn) updfn(cls, &n->_bst); \
905 /* Our child has a red parent. That's the new focus node. \
906 * Since it's red, it has a black parent. \
908 plink = path.p[--path.k]; p = (struct rbnode *)*plink; \
910 /* If the node has a red sibling then we can blacken this node \
911 * and its sibling. If the parent is the root, then the tree \
912 * got taller; otherwise, redden the parent and continue \
915 s = (struct rbnode *)p->_bst.left; \
916 if (s && s->f&RBF_RED) { \
917 V( fprintf(stderr, "RBTREE JOIN red sibling " \
918 "(" #right " child): %s\n", \
919 path.k ? "ascend" : "extend tree"); ) \
920 n->f &= ~RBF_RED; s->f &= ~RBF_RED; \
921 if (updfn) { updfn(cls, &n->_bst); updfn(cls, &p->_bst); } \
922 if (!path.k) { blkht++; break; } \
923 p->f |= RBF_RED; continue; \
926 /* The node has a red right child and a black parent, but no \
937 V( fputs("RBTREE JOIN no red sibling (" #right " child)\n", \
939 p->_bst.right = n->_bst.left; n->_bst.left = &p->_bst; \
940 n->f &= ~RBF_RED; p->f |= RBF_RED; \
941 if (updfn) { updfn(cls, &p->_bst); updfn(cls, &n->_bst); } \
946 /* Return the result. */ \
949 FIXUP_JOIN(left, lht, right, rht);
951 FIXUP_JOIN(right, rht, left, lht);
954 /* Follow the rest of the path up to the root, updating the nodes. */
955 if (updfn) while (path.k) updfn(cls, *path.p[--path.k]);
958 /* All done. Fix up the root pointers and return the new black-height. */
960 *left = 0; *right = 0; *root_out = root; return (blkht);
963 /* --- @rbtree_split@ --- *
965 * Arguments: @struct bstree_nodecls *cls@ = node class for the tree
966 * @struct bstnode *left_out@ = where to leave the root of the
967 * resulting left tree
968 * @int *lht_out@ = where to leave the black-height of the left
969 * tree, or null to discard this information
970 * @int *mht_out@ = where to leave the black-height of the
971 * middle node (either zero or one), or null to discard
973 * @struct bstnode *rirght_out@ = where to leave the root of the
974 * resulting right tree
975 * @int *rht_out@ = where to leave the black-height of the right
976 * tree, or null to discard this information
977 * @struct rbpath *path@ = full or empty path at which to split
980 * Returns: A pointer to the resulting middle node, or null.
982 * Use: Split a tree into two at an indicated place.
984 * The splitting operation produces two trees, a `left tree'
985 * containing every node preceding the given path, and a `right
986 * tree' containing every node following the path. If the path
987 * is full, i.e., it denotes a node in the input tree, then that
988 * becomes the `middle node', which does not appear in either
989 * tree, and is returned separately.
992 void *rbtree_split(struct bstree_nodecls *cls,
993 struct bstnode **left_out, int *lht_out,
995 struct bstnode **right_out, int *rht_out,
998 struct bstnode *left, *right, *sub, **next, **link;
999 struct rbnode *parent, *node, *mid;
1000 int k, blkht, lht, rht, subht;
1003 /* The basic idea is to work up the tree, following the provided path,
1004 * maintaining left and right trees. When we come across a node with a
1005 * leftward link, then we join that node and its right subtree onto our
1006 * right tree; and %%\emph{vice-versa}%%.
1009 * ,----|------' `---------|-,
1011 * ,---' `---,| ,-|-' `---,
1013 * / \ /| \ / \ | / \
1015 * / \ / \ / \ | / \ / \ /|\ / \ / \
1016 * * * * * * *| * * * * * | * * * * *
1019 * The conceptual difficulty lies in how to initialize the left and right
1022 * The other fiddly part is keeping track of the black-heights as we work
1026 /* Retrieve the designated node. */
1027 k = path->k; link = path->p[k]; mid = (struct rbnode *)*link;
1029 /* The path is full, i.e., it terminates in a link to a node, which will
1030 * be the final mid node. Initialize the left and right trees to the
1031 * node's left and right subtrees. Work out their black-heights -- this
1032 * will save effort later, because we know that they'll be equal.
1033 * Forcibly blacken the roots of the trees, and fix the heights as
1037 /* Initialize the left and right trees. */
1038 left = mid->_bst.left; right = mid->_bst.right;
1040 /* Initialize the black-heights. The two subtrees must have the same
1041 * black-height initially, but we must blacken the roots, and that might
1042 * introduce a difference.
1044 lht = rht = blkht = rbtree_height((struct rbnode *)left);
1046 node = (struct rbnode *)left;
1047 if (node->f&RBF_RED) { node->f &= ~RBF_RED; lht++; }
1050 node = (struct rbnode *)right;
1051 if (node->f&RBF_RED) { node->f &= ~RBF_RED; rht++; }
1054 /* Clear the split node's links, so that it's a standalone singleton
1055 * tree. If the split node is black then its height was one more than
1056 * its children's. If it's red, then blacken it because it's a root now.
1058 mid->_bst.left = mid->_bst.right = 0;
1059 if (!(mid->f&RBF_RED)) blkht++;
1060 else mid->f &= ~RBF_RED;
1062 /* Special case: the split node is the tree root.
1064 * This is only `special' because the other case ascends one step higher
1065 * in the tree, so we should do the same here.
1069 /* Prefetch the next node up the path. */
1070 next = path->p[--k]; parent = (struct rbnode *)*next;
1072 /* The path is empty, i.e., it terminates in a null link, and the final
1073 * mid node will be null. The obvious thing to do is to initialize the
1074 * left and right trees to be empty, but that will end up doing too much
1075 * work. If we examine the diagram above, we see that there will be an
1076 * intact subtree on one side of the split line. Working step-by-step
1077 * risks messing with the structure of that subtree for no benefit: if
1078 * the root of some inner subtree is red then we'll end up blackening it
1079 * because the root of a tree must be black -- but then its height will
1080 * differ from its sibling's when we come to join them together again and
1081 * we'll have to rebalance.
1083 * Instead, we note the direction of the final null link. Every further
1084 * link in the path that's in the same direction means that we're still
1085 * searching for the initial subtree root.
1088 /* Special case: the tree is actually empty. */
1089 if (!k) { left = right = 0; lht = rht = 0; goto end; }
1091 /* Retrieve the parent node and split into cases according to the link
1094 next = path->p[--k]; node = (struct rbnode *)*next; blkht = 0;
1095 if (link == &node->_bst.left)
1096 #define INIT_SPLIT_EMPTY(left, lht, right, rht) do { \
1097 /* The null link points leftwards, so the we're searching to \
1098 * bound the initial right tree. \
1103 /* We've decided to include the current node in the initial \
1104 * tree, so update the black-height. \
1106 if (!(node->f&RBF_RED)) blkht++; \
1108 /* The current node is the tree root. There can be nothing \
1112 left = 0; lht = 0; \
1113 right = &node->_bst; rht = blkht; \
1117 /* Ascend the tree and check the link direction. */ \
1118 link = next; next = path->p[--k]; \
1119 parent = (struct rbnode *)*next; \
1120 if (link != &parent->_bst.left) break; \
1121 node = parent; link = next; \
1124 /* Establish the left and right trees. */ \
1125 left = 0; lht = 0; \
1126 right = &node->_bst; rht = blkht; \
1128 /* Make sure the root of the right tree is painted black. */ \
1129 if (node->f&RBF_RED) { rht++; node->f &= ~RBF_RED; } \
1131 INIT_SPLIT_EMPTY(left, lht, right, rht);
1133 INIT_SPLIT_EMPTY(right, rht, left, lht);
1134 #undef INIT_SPLIT_EMPTY
1137 /* Ascend the tree, accumulating additional material into the left or right
1138 * trees. This is actually much less complicated than it sounds.
1141 /* The state at this point is a little tricky.
1143 * There is a current node; @link@ holds a link to this node, and @blkht@
1144 * is its black-height. The subtree rooted at this current node has been
1145 * split, resulting in a left tree rooted at @left@, with black-height
1146 * @lht@, and a right tree rooted at @right@, with black-height @rht@,
1147 * and, depending on the initial path, possibly a mid node @mid@.
1149 * The node has a @parent@. The link to the parent is in @next@. The
1150 * parent and the current node's subling subtree must be accumulated into
1151 * the appropriate left or right tree. Note that the sibling subtree has
1152 * the same black-height as the current node.
1155 /* Take note of the parent node's flags because they'll be clobbered in
1160 /* Accumulate the parent and the sibling subtree onto the appropriate
1163 if (link == &parent->_bst.left) {
1164 sub = parent->_bst.right; subht = blkht;
1165 node = (struct rbnode *)sub;
1166 if (node && node->f&RBF_RED) { subht++; node->f &= ~RBF_RED; }
1167 rht = rbtree_join(cls, &right,
1168 &right, rht, &parent->_bst, &sub, subht);
1170 sub = parent->_bst.left; subht = blkht;
1171 node = (struct rbnode *)sub;
1172 if (node && node->f&RBF_RED) { subht++; node->f &= ~RBF_RED; }
1173 lht = rbtree_join(cls, &left,
1174 &sub, subht, &parent->_bst, &left, lht);
1177 /* If we've reached the root then we're done. */
1180 /* Update the black-height. */
1181 if (!(f&RBF_RED)) blkht++;
1183 /* Ascend the tree. */
1184 link = next; node = parent;
1185 next = path->p[--k]; parent = (struct rbnode *)*next;
1191 *left_out = left; if (lht_out) *lht_out = lht;
1192 *right_out = right; if (rht_out) *rht_out = rht;
1193 if (mht_out) *mht_out = mid ? 1 : 0;
1197 /* --- @rbtree_splitat@ --- *
1199 * Arguments: @struct bstnode *left_out@ = where to leave the root of the
1200 * resulting left tree
1201 * @int *lht_out@ = where to leave the black-height of the left
1202 * tree, or null to discard this information
1203 * @int *mht_out@ = where to leave the black-height of the
1204 * middle node (either zero or one), or null to discard
1206 * @struct bstnode *right_out@ = where to leave the root of the
1207 * resulting right tree
1208 * @int *rht_out@ = where to leave the black-height of the right
1209 * tree, or null to discard this information
1210 * @struct bstnode **root@ = address of the root link of the
1212 * @const void *key@ = key at which to split the tree.
1214 * Returns: A pointer to the matching middle node, or null.
1216 * Use: Split a tree into two at an indicated key.
1218 * The splitting operation produces two trees, a `left tree'
1219 * containing every node whose key is less than @key@, and a
1220 * `right tree' containing every node whose key is greater than
1221 * @key@. If a node matching the @key@ exists in the input
1222 * tree, then that becomes the `middle node', which does not
1223 * appear in either tree, and is returned separately.
1226 void *rbtree_splitat(struct bstree_nodecls *cls,
1227 struct bstnode **left_out, int *lht_out,
1229 struct bstnode **right_out, int *rht_out,
1230 struct bstnode **root, const void *key)
1234 bstree_probe(cls, root, (/*unconst*/ void *)key, path.p, &path.k);
1235 return (rbtree_split(cls, left_out, lht_out, mht_out, right_out, rht_out,
1239 /* --- @rbtree_splitroot@ --- *
1241 * Arguments: @struct bstnode *left_out@ = where to leave the root of the
1242 * resulting left tree
1243 * @int *lht_out@ = where to leave the black-height of the left
1244 * tree, or null to discard this information
1245 * @int *mht_out@ = where to leave the black-height of the
1246 * middle node (either zero or one), or null to discard
1248 * @struct bstnode *right_out@ = where to leave the root of the
1249 * resulting right tree
1250 * @int *rht_out@ = where to leave the black-height of the right
1251 * tree, or null to discard this information
1252 * @struct bstnode **root@ = tree root node, or null
1253 * @int blkht@ = black-height of the tree, or %$-1$% if unknown
1255 * Returns: A pointer to the resulting middle node, or null.
1257 * Use: Split a tree into two at its root.
1259 * The splitting operation produces two trees, a `left tree'
1260 * containing every node preceding the root, and a `right
1261 * tree' containing every node following the root, together with
1262 * the root. If the root is null, then the left and right trees
1266 void *rbtree_splitroot(struct bstnode **left_out, int *lht_out,
1268 struct bstnode **right_out, int *rht_out,
1269 struct bstnode **root, int blkht)
1271 struct rbnode *left, *right, *node;
1274 node = (struct rbnode *)*root; *root = 0;
1276 *left_out = *right_out = 0;
1277 if (lht_out) *lht_out = 0;
1278 if (mht_out) *mht_out = 0;
1279 if (rht_out) *rht_out = 0;
1281 left = (struct rbnode *)node->_bst.left;
1282 right = (struct rbnode *)node->_bst.right;
1283 if (!lht_out && !rht_out) {
1284 if (left->f&RBF_RED) { left->f &= ~RBF_RED; }
1285 if (right->f&RBF_RED) { right->f &= ~RBF_RED; }
1287 if (blkht < 0) blkht = rbtree_height(node);
1288 lht = rht = blkht - 1;
1289 if (left && left->f&RBF_RED) { lht++; left->f &= ~RBF_RED; }
1290 if (right && right->f&RBF_RED) { rht++; right->f &= ~RBF_RED; }
1291 if (lht_out) *lht_out = lht;
1292 if (rht_out) *rht_out = rht;
1294 if (mht_out) *mht_out = 1;
1295 *left_out = left ? &left->_bst : 0;
1296 *right_out = right ? &right->_bst : 0;
1301 static const struct bstree_treeops rbtree_ops =
1302 { rbtree_join, rbtree_splitat, rbtree_splitroot };
1304 /* --- @rbtree_unisect@ --- *
1306 * Arguments: @struct bstree_nodecls *cls@ = node class for the tree
1307 * @struct bstnode **uni_out@ = where to write the union root
1308 * @int *uniht_out@ = where to put the union height (or null)
1309 * @struct bstnode **isect_out@ = where to write the
1311 * @int *isectht_out@ = where to put the intersection height (or
1313 * @struct bstnode *a@ = pointer to first operand root node
1314 * @int aht@ = first operand height, or %$-1$%
1315 * @struct bstnode *b@ = pointer to second operand root node
1316 * @int bht@ = second operand height, or %$-1$%
1320 * Use: Compute the union and intersection of the two operand trees.
1322 * The original trees are destroyed. Each node in the original
1323 * operands trees ends up in exactly one of the result trees.
1326 void rbtree_unisect(struct bstree_nodecls *cls,
1327 struct bstnode **uni_out, int *uniht_out,
1328 struct bstnode **isect_out, int *isectht_out,
1329 struct bstnode **aroot, int aht,
1330 struct bstnode **broot, int bht)
1332 struct bstnode *a, *b;
1333 struct bstree_setopstack stack[RBTREE_PATHMAX];
1335 a = *aroot; if (aht < 0) aht = rbtree_height((struct rbnode *)a);
1336 b = *broot; if (bht < 0) bht = rbtree_height((struct rbnode *)b);
1337 *aroot = *broot = 0;
1339 bstree_unisect(cls, uni_out, uniht_out, isect_out, isectht_out,
1340 a, aht, b, bht, &rbtree_ops, stack);
1343 /* --- @rbtree_diffsect@ --- *
1345 * Arguments: @struct bstree_nodecls *cls@ = node class for the tree
1346 * @struct bstnode **diff_out@ = where to write the difference
1348 * @int *diffht_out@ = where to put the difference height (or
1350 * @struct bstnode **isect_out@ = where to write the
1352 * @int *isectht_out@ = where to put the intersection height (or
1354 * @struct bstnode *a@ = pointer to first operand root node
1355 * @int aht@ = first operand height, or %$-1$%
1356 * @struct bstnode *b@ = pointer to second operand root node
1360 * Use: Compute the difference -- i.e., those nodes in %$a$% without
1361 * matching nodes in %$b$% -- and intersection of the two
1364 * The original tree %$a$% is destroyed. Each node in the
1365 * original operands tree ends up in exactly one of the result
1366 * trees. The input tree %$b$% is unchanged.
1369 void rbtree_diffsect(struct bstree_nodecls *cls,
1370 struct bstnode **diff_out, int *diffht_out,
1371 struct bstnode **isect_out, int *isectht_out,
1372 struct bstnode **aroot, int aht,
1373 struct bstnode **broot)
1375 struct bstnode *a, *b;
1376 struct bstree_setopstack stack[RBTREE_PATHMAX];
1378 a = *aroot; if (aht < 0) aht = rbtree_height((struct rbnode *)a);
1381 bstree_diffsect(cls, diff_out, diffht_out, isect_out, isectht_out,
1382 a, aht, b, &rbtree_ops, stack);