xref: /freebsd/share/man/man3/tree.3 (revision 1165fc9a526630487a1feb63daef65c5aee1a583)
1.\"	$OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $
2.\"
3.\" Copyright 2002 Niels Provos <provos@citi.umich.edu>
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\"    notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\"    notice, this list of conditions and the following disclaimer in the
13.\"    documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\"    must display the following acknowledgement:
16.\"      This product includes software developed by Niels Provos.
17.\" 4. The name of the author may not be used to endorse or promote products
18.\"    derived from this software without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30.\"
31.\" $FreeBSD$
32.\"
33.Dd July 27, 2020
34.Dt TREE 3
35.Os
36.Sh NAME
37.Nm SPLAY_PROTOTYPE ,
38.Nm SPLAY_GENERATE ,
39.Nm SPLAY_ENTRY ,
40.Nm SPLAY_HEAD ,
41.Nm SPLAY_INITIALIZER ,
42.Nm SPLAY_ROOT ,
43.Nm SPLAY_EMPTY ,
44.Nm SPLAY_NEXT ,
45.Nm SPLAY_MIN ,
46.Nm SPLAY_MAX ,
47.Nm SPLAY_FIND ,
48.Nm SPLAY_LEFT ,
49.Nm SPLAY_RIGHT ,
50.Nm SPLAY_FOREACH ,
51.Nm SPLAY_INIT ,
52.Nm SPLAY_INSERT ,
53.Nm SPLAY_REMOVE ,
54.Nm RB_PROTOTYPE ,
55.Nm RB_PROTOTYPE_STATIC ,
56.Nm RB_PROTOTYPE_INSERT ,
57.Nm RB_PROTOTYPE_INSERT_COLOR ,
58.Nm RB_PROTOTYPE_REMOVE ,
59.Nm RB_PROTOTYPE_REMOVE_COLOR ,
60.Nm RB_PROTOTYPE_FIND ,
61.Nm RB_PROTOTYPE_NFIND ,
62.Nm RB_PROTOTYPE_NEXT ,
63.Nm RB_PROTOTYPE_PREV ,
64.Nm RB_PROTOTYPE_MINMAX ,
65.Nm RB_PROTOTYPE_REINSERT ,
66.Nm RB_GENERATE ,
67.Nm RB_GENERATE_STATIC ,
68.Nm RB_GENERATE_INSERT ,
69.Nm RB_GENERATE_INSERT_COLOR ,
70.Nm RB_GENERATE_REMOVE ,
71.Nm RB_GENERATE_REMOVE_COLOR ,
72.Nm RB_GENERATE_FIND ,
73.Nm RB_GENERATE_NFIND ,
74.Nm RB_GENERATE_NEXT ,
75.Nm RB_GENERATE_PREV ,
76.Nm RB_GENERATE_MINMAX ,
77.Nm RB_GENERATE_REINSERT ,
78.Nm RB_ENTRY ,
79.Nm RB_HEAD ,
80.Nm RB_INITIALIZER ,
81.Nm RB_ROOT ,
82.Nm RB_EMPTY ,
83.Nm RB_NEXT ,
84.Nm RB_PREV ,
85.Nm RB_MIN ,
86.Nm RB_MAX ,
87.Nm RB_FIND ,
88.Nm RB_NFIND ,
89.Nm RB_LEFT ,
90.Nm RB_RIGHT ,
91.Nm RB_PARENT ,
92.Nm RB_FOREACH ,
93.Nm RB_FOREACH_FROM ,
94.Nm RB_FOREACH_SAFE ,
95.Nm RB_FOREACH_REVERSE ,
96.Nm RB_FOREACH_REVERSE_FROM ,
97.Nm RB_FOREACH_REVERSE_SAFE ,
98.Nm RB_INIT ,
99.Nm RB_INSERT ,
100.Nm RB_REMOVE ,
101.Nm RB_REINSERT ,
102.Nm RB_AUGMENT
103.Nm RB_UPDATE_AUGMENT
104.Nd "implementations of splay and rank-balanced (wavl) trees"
105.Sh SYNOPSIS
106.In sys/tree.h
107.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP
108.Fn SPLAY_GENERATE NAME TYPE FIELD CMP
109.Fn SPLAY_ENTRY TYPE
110.Fn SPLAY_HEAD HEADNAME TYPE
111.Ft "struct TYPE *"
112.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head"
113.Fn SPLAY_ROOT "SPLAY_HEAD *head"
114.Ft bool
115.Fn SPLAY_EMPTY "SPLAY_HEAD *head"
116.Ft "struct TYPE *"
117.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
118.Ft "struct TYPE *"
119.Fn SPLAY_MIN NAME "SPLAY_HEAD *head"
120.Ft "struct TYPE *"
121.Fn SPLAY_MAX NAME "SPLAY_HEAD *head"
122.Ft "struct TYPE *"
123.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm"
124.Ft "struct TYPE *"
125.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME"
126.Ft "struct TYPE *"
127.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME"
128.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head"
129.Ft void
130.Fn SPLAY_INIT "SPLAY_HEAD *head"
131.Ft "struct TYPE *"
132.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
133.Ft "struct TYPE *"
134.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm"
135.Fn RB_PROTOTYPE NAME TYPE FIELD CMP
136.Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP
137.Fn RB_PROTOTYPE_INSERT NAME TYPE ATTR
138.Fn RB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR
139.Fn RB_PROTOTYPE_REMOVE NAME TYPE ATTR
140.Fn RB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR
141.Fn RB_PROTOTYPE_FIND NAME TYPE ATTR
142.Fn RB_PROTOTYPE_NFIND NAME TYPE ATTR
143.Fn RB_PROTOTYPE_NEXT NAME TYPE ATTR
144.Fn RB_PROTOTYPE_PREV NAME TYPE ATTR
145.Fn RB_PROTOTYPE_MINMAX NAME TYPE ATTR
146.Fn RB_PROTOTYPE_REINSERT NAME TYPE ATTR
147.Fn RB_GENERATE NAME TYPE FIELD CMP
148.Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP
149.Fn RB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR
150.Fn RB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR
151.Fn RB_GENERATE_REMOVE NAME TYPE FIELD ATTR
152.Fn RB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR
153.Fn RB_GENERATE_FIND NAME TYPE FIELD CMP ATTR
154.Fn RB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR
155.Fn RB_GENERATE_NEXT NAME TYPE FIELD ATTR
156.Fn RB_GENERATE_PREV NAME TYPE FIELD ATTR
157.Fn RB_GENERATE_MINMAX NAME TYPE FIELD ATTR
158.Fn RB_GENERATE_REINSERT NAME TYPE FIELD CMP ATTR
159.Fn RB_ENTRY TYPE
160.Fn RB_HEAD HEADNAME TYPE
161.Fn RB_INITIALIZER "RB_HEAD *head"
162.Ft "struct TYPE *"
163.Fn RB_ROOT "RB_HEAD *head"
164.Ft "bool"
165.Fn RB_EMPTY "RB_HEAD *head"
166.Ft "struct TYPE *"
167.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm"
168.Ft "struct TYPE *"
169.Fn RB_PREV NAME "RB_HEAD *head" "struct TYPE *elm"
170.Ft "struct TYPE *"
171.Fn RB_MIN NAME "RB_HEAD *head"
172.Ft "struct TYPE *"
173.Fn RB_MAX NAME "RB_HEAD *head"
174.Ft "struct TYPE *"
175.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm"
176.Ft "struct TYPE *"
177.Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm"
178.Ft "struct TYPE *"
179.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME"
180.Ft "struct TYPE *"
181.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME"
182.Ft "struct TYPE *"
183.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
184.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head"
185.Fn RB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME"
186.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
187.Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head"
188.Fn RB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME"
189.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
190.Ft void
191.Fn RB_INIT "RB_HEAD *head"
192.Ft "struct TYPE *"
193.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm"
194.Ft "struct TYPE *"
195.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm"
196.Ft "struct TYPE *"
197.Fn RB_REINSERT NAME "RB_HEAD *head" "struct TYPE *elm"
198.Ft "void"
199.Fn RB_AUGMENT NAME "struct TYPE *elm"
200.Ft "void"
201.Fn RB_UPDATE_AUGMENT NAME "struct TYPE *elm"
202.Sh DESCRIPTION
203These macros define data structures for different types of trees:
204splay trees and rank-balanced (wavl) trees.
205.Pp
206In the macro definitions,
207.Fa TYPE
208is the name tag of a user defined structure that must contain a field of type
209.Vt SPLAY_ENTRY ,
210or
211.Vt RB_ENTRY ,
212named
213.Fa ENTRYNAME .
214The argument
215.Fa HEADNAME
216is the name tag of a user defined structure that must be declared
217using the macros
218.Fn SPLAY_HEAD ,
219or
220.Fn RB_HEAD .
221The argument
222.Fa NAME
223has to be a unique name prefix for every tree that is defined.
224.Pp
225The function prototypes are declared with
226.Fn SPLAY_PROTOTYPE ,
227.Fn RB_PROTOTYPE ,
228or
229.Fn RB_PROTOTYPE_STATIC .
230The function bodies are generated with
231.Fn SPLAY_GENERATE ,
232.Fn RB_GENERATE ,
233or
234.Fn RB_GENERATE_STATIC .
235See the examples below for further explanation of how these macros are used.
236.Sh SPLAY TREES
237A splay tree is a self-organizing data structure.
238Every operation on the tree causes a splay to happen.
239The splay moves the requested
240node to the root of the tree and partly rebalances it.
241.Pp
242This has the benefit that request locality causes faster lookups as
243the requested nodes move to the top of the tree.
244On the other hand, every lookup causes memory writes.
245.Pp
246The Balance Theorem bounds the total access time for
247.Ar m
248operations and
249.Ar n
250inserts on an initially empty tree as
251.Fn O "\*[lp]m + n\*[rp]lg n" .
252The
253amortized cost for a sequence of
254.Ar m
255accesses to a splay tree is
256.Fn O "lg n" .
257.Pp
258A splay tree is headed by a structure defined by the
259.Fn SPLAY_HEAD
260macro.
261A
262structure is declared as follows:
263.Bd -ragged -offset indent
264.Fn SPLAY_HEAD HEADNAME TYPE
265.Va head ;
266.Ed
267.Pp
268where
269.Fa HEADNAME
270is the name of the structure to be defined, and struct
271.Fa TYPE
272is the type of the elements to be inserted into the tree.
273.Pp
274The
275.Fn SPLAY_ENTRY
276macro declares a structure that allows elements to be connected in the tree.
277.Pp
278In order to use the functions that manipulate the tree structure,
279their prototypes need to be declared with the
280.Fn SPLAY_PROTOTYPE
281macro,
282where
283.Fa NAME
284is a unique identifier for this particular tree.
285The
286.Fa TYPE
287argument is the type of the structure that is being managed
288by the tree.
289The
290.Fa FIELD
291argument is the name of the element defined by
292.Fn SPLAY_ENTRY .
293.Pp
294The function bodies are generated with the
295.Fn SPLAY_GENERATE
296macro.
297It takes the same arguments as the
298.Fn SPLAY_PROTOTYPE
299macro, but should be used only once.
300.Pp
301Finally,
302the
303.Fa CMP
304argument is the name of a function used to compare tree nodes
305with each other.
306The function takes two arguments of type
307.Vt "struct TYPE *" .
308If the first argument is smaller than the second, the function returns a
309value smaller than zero.
310If they are equal, the function returns zero.
311Otherwise, it should return a value greater than zero.
312The compare
313function defines the order of the tree elements.
314.Pp
315The
316.Fn SPLAY_INIT
317macro initializes the tree referenced by
318.Fa head .
319.Pp
320The splay tree can also be initialized statically by using the
321.Fn SPLAY_INITIALIZER
322macro like this:
323.Bd -ragged -offset indent
324.Fn SPLAY_HEAD HEADNAME TYPE
325.Va head
326=
327.Fn SPLAY_INITIALIZER &head ;
328.Ed
329.Pp
330The
331.Fn SPLAY_INSERT
332macro inserts the new element
333.Fa elm
334into the tree.
335.Pp
336The
337.Fn SPLAY_REMOVE
338macro removes the element
339.Fa elm
340from the tree pointed by
341.Fa head .
342.Pp
343The
344.Fn SPLAY_FIND
345macro can be used to find a particular element in the tree.
346.Bd -literal -offset indent
347struct TYPE find, *res;
348find.key = 30;
349res = SPLAY_FIND(NAME, head, &find);
350.Ed
351.Pp
352The
353.Fn SPLAY_ROOT ,
354.Fn SPLAY_MIN ,
355.Fn SPLAY_MAX ,
356and
357.Fn SPLAY_NEXT
358macros can be used to traverse the tree:
359.Bd -literal -offset indent
360for (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np))
361.Ed
362.Pp
363Or, for simplicity, one can use the
364.Fn SPLAY_FOREACH
365macro:
366.Bd -ragged -offset indent
367.Fn SPLAY_FOREACH np NAME head
368.Ed
369.Pp
370The
371.Fn SPLAY_EMPTY
372macro should be used to check whether a splay tree is empty.
373.Sh RANK-BALANCED TREES
374Rank-balanced (RB) trees are a framework for defining height-balanced
375binary search trees, including AVL and red-black trees.
376Each tree node has an associated rank.
377Balance conditions are expressed by conditions on the differences in
378rank between any node and its children.
379Rank differences are stored in each tree node.
380.Pp
381The balance conditions implemented by the RB macros lead to weak AVL
382(wavl) trees, which combine the best aspects of AVL and red-black
383trees.
384Wavl trees rebalance after an insertion in the same way AVL trees do,
385with the same worst-case time as red-black trees offer, and with
386better balance in the resulting tree.
387Wavl trees rebalance after a removal in a way that requires less
388restructuring, in the worst case, than either AVL or red-black trees
389do.
390Removals can lead to a tree almost as unbalanced as a red-black
391tree; insertions lead to a tree becoming as balanced as an AVL tree.
392.Pp
393A rank-balanced tree is headed by a structure defined by the
394.Fn RB_HEAD
395macro.
396A
397structure is declared as follows:
398.Bd -ragged -offset indent
399.Fn RB_HEAD HEADNAME TYPE
400.Va head ;
401.Ed
402.Pp
403where
404.Fa HEADNAME
405is the name of the structure to be defined, and struct
406.Fa TYPE
407is the type of the elements to be inserted into the tree.
408.Pp
409The
410.Fn RB_ENTRY
411macro declares a structure that allows elements to be connected in the tree.
412.Pp
413In order to use the functions that manipulate the tree structure,
414their prototypes need to be declared with the
415.Fn RB_PROTOTYPE
416or
417.Fn RB_PROTOTYPE_STATIC
418macro,
419where
420.Fa NAME
421is a unique identifier for this particular tree.
422The
423.Fa TYPE
424argument is the type of the structure that is being managed
425by the tree.
426The
427.Fa FIELD
428argument is the name of the element defined by
429.Fn RB_ENTRY .
430Individual prototypes can be declared with
431.Fn RB_PROTOTYPE_INSERT ,
432.Fn RB_PROTOTYPE_INSERT_COLOR ,
433.Fn RB_PROTOTYPE_REMOVE ,
434.Fn RB_PROTOTYPE_REMOVE_COLOR ,
435.Fn RB_PROTOTYPE_FIND ,
436.Fn RB_PROTOTYPE_NFIND ,
437.Fn RB_PROTOTYPE_NEXT ,
438.Fn RB_PROTOTYPE_PREV ,
439.Fn RB_PROTOTYPE_MINMAX ,
440and
441.Fn RB_PROTOTYPE_REINSERT
442in case not all functions are required.
443The individual prototype macros expect
444.Fa NAME ,
445.Fa TYPE ,
446and
447.Fa ATTR
448arguments.
449The
450.Fa ATTR
451argument must be empty for global functions or
452.Fa static
453for static functions.
454.Pp
455The function bodies are generated with the
456.Fn RB_GENERATE
457or
458.Fn RB_GENERATE_STATIC
459macro.
460These macros take the same arguments as the
461.Fn RB_PROTOTYPE
462and
463.Fn RB_PROTOTYPE_STATIC
464macros, but should be used only once.
465As an alternative individual function bodies are generated with the
466.Fn RB_GENERATE_INSERT ,
467.Fn RB_GENERATE_INSERT_COLOR ,
468.Fn RB_GENERATE_REMOVE ,
469.Fn RB_GENERATE_REMOVE_COLOR ,
470.Fn RB_GENERATE_FIND ,
471.Fn RB_GENERATE_NFIND ,
472.Fn RB_GENERATE_NEXT ,
473.Fn RB_GENERATE_PREV ,
474.Fn RB_GENERATE_MINMAX ,
475and
476.Fn RB_GENERATE_REINSERT
477macros.
478.Pp
479Finally,
480the
481.Fa CMP
482argument is the name of a function used to compare tree nodes
483with each other.
484The function takes two arguments of type
485.Vt "struct TYPE *" .
486If the first argument is smaller than the second, the function returns a
487value smaller than zero.
488If they are equal, the function returns zero.
489Otherwise, it should return a value greater than zero.
490The compare
491function defines the order of the tree elements.
492.Pp
493The
494.Fn RB_INIT
495macro initializes the tree referenced by
496.Fa head .
497.Pp
498The rank-balanced tree can also be initialized statically by using the
499.Fn RB_INITIALIZER
500macro like this:
501.Bd -ragged -offset indent
502.Fn RB_HEAD HEADNAME TYPE
503.Va head
504=
505.Fn RB_INITIALIZER &head ;
506.Ed
507.Pp
508The
509.Fn RB_INSERT
510macro inserts the new element
511.Fa elm
512into the tree.
513.Pp
514The
515.Fn RB_REMOVE
516macro removes the element
517.Fa elm
518from the tree pointed by
519.Fa head .
520.Pp
521The
522.Fn RB_FIND
523and
524.Fn RB_NFIND
525macros can be used to find a particular element in the tree.
526.Bd -literal -offset indent
527struct TYPE find, *res;
528find.key = 30;
529res = RB_FIND(NAME, head, &find);
530.Ed
531.Pp
532The
533.Fn RB_ROOT ,
534.Fn RB_MIN ,
535.Fn RB_MAX ,
536.Fn RB_NEXT ,
537and
538.Fn RB_PREV
539macros can be used to traverse the tree:
540.Pp
541.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))"
542.Pp
543Or, for simplicity, one can use the
544.Fn RB_FOREACH
545or
546.Fn RB_FOREACH_REVERSE
547macro:
548.Bd -ragged -offset indent
549.Fn RB_FOREACH np NAME head
550.Ed
551.Pp
552The macros
553.Fn RB_FOREACH_SAFE
554and
555.Fn RB_FOREACH_REVERSE_SAFE
556traverse the tree referenced by head
557in a forward or reverse direction respectively,
558assigning each element in turn to np.
559However, unlike their unsafe counterparts,
560they permit both the removal of np
561as well as freeing it from within the loop safely
562without interfering with the traversal.
563.Pp
564Both
565.Fn RB_FOREACH_FROM
566and
567.Fn RB_FOREACH_REVERSE_FROM
568may be used to continue an interrupted traversal
569in a forward or reverse direction respectively.
570The head pointer is not required.
571The pointer to the node from where to resume the traversal
572should be passed as their last argument,
573and will be overwritten to provide safe traversal.
574.Pp
575The
576.Fn RB_EMPTY
577macro should be used to check whether a rank-balanced tree is empty.
578.Pp
579The
580.Fn RB_REINSERT
581macro updates the position of the element
582.Fa elm
583in the tree.
584This must be called if a member of a
585.Nm tree
586is modified in a way that affects comparison, such as by modifying
587a node's key.
588This is a lower overhead alternative to removing the element
589and reinserting it again.
590.Pp
591The
592.Fn RB_AUGMENT
593macro updates augmentation data of the element
594.Fa elm
595in the tree.
596By default, it has no effect.
597It is not meant to be invoked by the RB user.
598If
599.Fn RB_AUGMENT
600is defined by the RB user, then when an element is inserted or removed
601from the tree, it is invoked for every element in the tree that is the
602root of an altered subtree, working from the bottom of the tree up to
603the top.
604It is typically used to maintain some associative accumulation of tree
605elements, such as sums, minima, maxima, and the like.
606.Pp
607The
608.Fn RB_UPDATE_AUGMENT
609macro updates augmentation data of the element
610.Fa elm
611and its ancestors in the tree.
612If RB_AUGMENT is defined by the RB user, then when an element in the
613tree is changed, without changing the order of items in the tree,
614invoking this function on that element restores consistency of the
615augmentation state of the tree as if the element had been removed and
616inserted again.
617.Sh EXAMPLES
618The following example demonstrates how to declare a rank-balanced tree
619holding integers.
620Values are inserted into it and the contents of the tree are printed
621in order.
622To maintain the sum of the values in the tree, each element maintains
623the sum of its value and the sums from its left and right subtrees.
624Lastly, the internal structure of the tree is printed.
625.Bd -literal -offset 3n
626#include <sys/tree.h>
627#include <err.h>
628#include <stdio.h>
629#include <stdlib.h>
630
631struct node {
632	RB_ENTRY(node) entry;
633	int i, sum;
634};
635
636int
637intcmp(struct node *e1, struct node *e2)
638{
639	return (e1->i < e2->i ? -1 : e1->i > e2->i);
640}
641
642int
643sumaug(struct node *e)
644{
645	e->sum = e->i;
646	if (RB_LEFT(e, entry) != NULL)
647		e->sum += RB_LEFT(e, entry)->sum;
648	if (RB_RIGHT(e, entry) != NULL)
649		e->sum += RB_RIGHT(e, entry)->sum;
650}
651#define RB_AUGMENT(entry) sumaug(entry)
652
653RB_HEAD(inttree, node) head = RB_INITIALIZER(&head);
654RB_GENERATE(inttree, node, entry, intcmp)
655
656int testdata[] = {
657	20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18,
658	7, 11, 14
659};
660
661void
662print_tree(struct node *n)
663{
664	struct node *left, *right;
665
666	if (n == NULL) {
667		printf("nil");
668		return;
669	}
670	left = RB_LEFT(n, entry);
671	right = RB_RIGHT(n, entry);
672	if (left == NULL && right == NULL)
673		printf("%d", n->i);
674	else {
675		printf("%d(", n->i);
676		print_tree(left);
677		printf(",");
678		print_tree(right);
679		printf(")");
680	}
681}
682
683int
684main(void)
685{
686	int i;
687	struct node *n;
688
689	for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) {
690		if ((n = malloc(sizeof(struct node))) == NULL)
691			err(1, NULL);
692		n->i = testdata[i];
693		RB_INSERT(inttree, &head, n);
694	}
695
696	RB_FOREACH(n, inttree, &head) {
697		printf("%d\en", n->i);
698	}
699	print_tree(RB_ROOT(&head));
700	printf("Sum of values = %d\n", RB_ROOT(&head)->sum);
701	printf("\en");
702	return (0);
703}
704.Ed
705.Sh NOTES
706Trying to free a tree in the following way is a common error:
707.Bd -literal -offset indent
708SPLAY_FOREACH(var, NAME, head) {
709	SPLAY_REMOVE(NAME, head, var);
710	free(var);
711}
712free(head);
713.Ed
714.Pp
715Since
716.Va var
717is freed, the
718.Fn FOREACH
719macro refers to a pointer that may have been reallocated already.
720Proper code needs a second variable.
721.Bd -literal -offset indent
722for (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) {
723	nxt = SPLAY_NEXT(NAME, head, var);
724	SPLAY_REMOVE(NAME, head, var);
725	free(var);
726}
727.Ed
728.Pp
729Both
730.Fn RB_INSERT
731and
732.Fn SPLAY_INSERT
733return
734.Dv NULL
735if the element was inserted in the tree successfully, otherwise they
736return a pointer to the element with the colliding key.
737.Pp
738Accordingly,
739.Fn RB_REMOVE
740and
741.Fn SPLAY_REMOVE
742return the pointer to the removed element otherwise they return
743.Dv NULL
744to indicate an error.
745.Sh SEE ALSO
746.Xr arb 3 ,
747.Xr queue 3
748.Rs
749.%A "Bernhard Haeupler"
750.%A "Siddhartha Sen"
751.%A "Robert E. Tarjan"
752.%T "Rank-Balanced Trees"
753.%U "http://sidsen.azurewebsites.net/papers/rb-trees-talg.pdf"
754.%J "ACM Transactions on Algorithms"
755.%V "11"
756.%N "4"
757.%D "June 2015"
758.Re
759.Sh HISTORY
760The tree macros first appeared in
761.Fx 4.6 .
762.Sh AUTHORS
763The author of the tree macros is
764.An Niels Provos .
765