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