xref: /freebsd/share/man/man3/tree.3 (revision fad4b12b9007f59d78a92b35669ffb13bd71b82f)
187f5f0ecSDag-Erling Smørgrav.\"	$OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $
2480565d5SRuslan Ermilov.\"
3480565d5SRuslan Ermilov.\" Copyright 2002 Niels Provos <provos@citi.umich.edu>
4480565d5SRuslan Ermilov.\" All rights reserved.
5480565d5SRuslan Ermilov.\"
6480565d5SRuslan Ermilov.\" Redistribution and use in source and binary forms, with or without
7480565d5SRuslan Ermilov.\" modification, are permitted provided that the following conditions
8480565d5SRuslan Ermilov.\" are met:
9480565d5SRuslan Ermilov.\" 1. Redistributions of source code must retain the above copyright
10480565d5SRuslan Ermilov.\"    notice, this list of conditions and the following disclaimer.
11480565d5SRuslan Ermilov.\" 2. Redistributions in binary form must reproduce the above copyright
12480565d5SRuslan Ermilov.\"    notice, this list of conditions and the following disclaimer in the
13480565d5SRuslan Ermilov.\"    documentation and/or other materials provided with the distribution.
14480565d5SRuslan Ermilov.\" 3. All advertising materials mentioning features or use of this software
15480565d5SRuslan Ermilov.\"    must display the following acknowledgement:
16480565d5SRuslan Ermilov.\"      This product includes software developed by Niels Provos.
17480565d5SRuslan Ermilov.\" 4. The name of the author may not be used to endorse or promote products
18480565d5SRuslan Ermilov.\"    derived from this software without specific prior written permission.
19480565d5SRuslan Ermilov.\"
20480565d5SRuslan Ermilov.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21480565d5SRuslan Ermilov.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22480565d5SRuslan Ermilov.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23480565d5SRuslan Ermilov.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24480565d5SRuslan Ermilov.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25480565d5SRuslan Ermilov.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26480565d5SRuslan Ermilov.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27480565d5SRuslan Ermilov.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28480565d5SRuslan Ermilov.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29480565d5SRuslan Ermilov.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30480565d5SRuslan Ermilov.\"
31480565d5SRuslan Ermilov.\" $FreeBSD$
32480565d5SRuslan Ermilov.\"
33ac0879c3SEdward Tomasz Napierala.Dd May 8, 2019
3487f5f0ecSDag-Erling Smørgrav.Dt TREE 3
3587f5f0ecSDag-Erling Smørgrav.Os
3687f5f0ecSDag-Erling Smørgrav.Sh NAME
3787f5f0ecSDag-Erling Smørgrav.Nm SPLAY_PROTOTYPE ,
3887f5f0ecSDag-Erling Smørgrav.Nm SPLAY_GENERATE ,
3987f5f0ecSDag-Erling Smørgrav.Nm SPLAY_ENTRY ,
4087f5f0ecSDag-Erling Smørgrav.Nm SPLAY_HEAD ,
4187f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INITIALIZER ,
4287f5f0ecSDag-Erling Smørgrav.Nm SPLAY_ROOT ,
4387f5f0ecSDag-Erling Smørgrav.Nm SPLAY_EMPTY ,
4487f5f0ecSDag-Erling Smørgrav.Nm SPLAY_NEXT ,
4587f5f0ecSDag-Erling Smørgrav.Nm SPLAY_MIN ,
4687f5f0ecSDag-Erling Smørgrav.Nm SPLAY_MAX ,
4787f5f0ecSDag-Erling Smørgrav.Nm SPLAY_FIND ,
4887f5f0ecSDag-Erling Smørgrav.Nm SPLAY_LEFT ,
4987f5f0ecSDag-Erling Smørgrav.Nm SPLAY_RIGHT ,
5087f5f0ecSDag-Erling Smørgrav.Nm SPLAY_FOREACH ,
5187f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INIT ,
5287f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INSERT ,
5387f5f0ecSDag-Erling Smørgrav.Nm SPLAY_REMOVE ,
5487f5f0ecSDag-Erling Smørgrav.Nm RB_PROTOTYPE ,
55d72cd779SJason Evans.Nm RB_PROTOTYPE_STATIC ,
5651782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_INSERT ,
5751782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_INSERT_COLOR ,
5851782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_REMOVE ,
5951782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_REMOVE_COLOR ,
6051782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_FIND ,
6151782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_NFIND ,
6251782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_NEXT ,
6351782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_PREV ,
6451782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_MINMAX ,
6587f5f0ecSDag-Erling Smørgrav.Nm RB_GENERATE ,
66d72cd779SJason Evans.Nm RB_GENERATE_STATIC ,
6751782e3aSKonstantin Belousov.Nm RB_GENERATE_INSERT ,
6851782e3aSKonstantin Belousov.Nm RB_GENERATE_INSERT_COLOR ,
6951782e3aSKonstantin Belousov.Nm RB_GENERATE_REMOVE ,
7051782e3aSKonstantin Belousov.Nm RB_GENERATE_REMOVE_COLOR ,
7151782e3aSKonstantin Belousov.Nm RB_GENERATE_FIND ,
7251782e3aSKonstantin Belousov.Nm RB_GENERATE_NFIND ,
7351782e3aSKonstantin Belousov.Nm RB_GENERATE_NEXT ,
7451782e3aSKonstantin Belousov.Nm RB_GENERATE_PREV ,
7551782e3aSKonstantin Belousov.Nm RB_GENERATE_MINMAX ,
7687f5f0ecSDag-Erling Smørgrav.Nm RB_ENTRY ,
7787f5f0ecSDag-Erling Smørgrav.Nm RB_HEAD ,
7887f5f0ecSDag-Erling Smørgrav.Nm RB_INITIALIZER ,
7987f5f0ecSDag-Erling Smørgrav.Nm RB_ROOT ,
8087f5f0ecSDag-Erling Smørgrav.Nm RB_EMPTY ,
8187f5f0ecSDag-Erling Smørgrav.Nm RB_NEXT ,
828e4fd0a1SJason Evans.Nm RB_PREV ,
8387f5f0ecSDag-Erling Smørgrav.Nm RB_MIN ,
8487f5f0ecSDag-Erling Smørgrav.Nm RB_MAX ,
8587f5f0ecSDag-Erling Smørgrav.Nm RB_FIND ,
8606115e08SJason Evans.Nm RB_NFIND ,
8787f5f0ecSDag-Erling Smørgrav.Nm RB_LEFT ,
8887f5f0ecSDag-Erling Smørgrav.Nm RB_RIGHT ,
8987f5f0ecSDag-Erling Smørgrav.Nm RB_PARENT ,
9087f5f0ecSDag-Erling Smørgrav.Nm RB_FOREACH ,
91bff27689SBruce M Simpson.Nm RB_FOREACH_FROM ,
929dbae282SGleb Smirnoff.Nm RB_FOREACH_SAFE ,
938e4fd0a1SJason Evans.Nm RB_FOREACH_REVERSE ,
94bff27689SBruce M Simpson.Nm RB_FOREACH_REVERSE_FROM ,
959dbae282SGleb Smirnoff.Nm RB_FOREACH_REVERSE_SAFE ,
9687f5f0ecSDag-Erling Smørgrav.Nm RB_INIT ,
9787f5f0ecSDag-Erling Smørgrav.Nm RB_INSERT ,
9887f5f0ecSDag-Erling Smørgrav.Nm RB_REMOVE
9987f5f0ecSDag-Erling Smørgrav.Nd "implementations of splay and red-black trees"
10087f5f0ecSDag-Erling Smørgrav.Sh SYNOPSIS
101480565d5SRuslan Ermilov.In sys/tree.h
102480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP
103480565d5SRuslan Ermilov.Fn SPLAY_GENERATE NAME TYPE FIELD CMP
104480565d5SRuslan Ermilov.Fn SPLAY_ENTRY TYPE
105480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
10687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
10787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head"
10887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT "SPLAY_HEAD *head"
109480565d5SRuslan Ermilov.Ft bool
11087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY "SPLAY_HEAD *head"
11187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
112480565d5SRuslan Ermilov.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
11387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
114480565d5SRuslan Ermilov.Fn SPLAY_MIN NAME "SPLAY_HEAD *head"
11587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
116480565d5SRuslan Ermilov.Fn SPLAY_MAX NAME "SPLAY_HEAD *head"
11787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
118480565d5SRuslan Ermilov.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm"
11987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
12087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME"
12187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
12287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME"
123480565d5SRuslan Ermilov.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head"
12487f5f0ecSDag-Erling Smørgrav.Ft void
12587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT "SPLAY_HEAD *head"
12687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
127480565d5SRuslan Ermilov.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
12887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
129480565d5SRuslan Ermilov.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm"
130480565d5SRuslan Ermilov.Fn RB_PROTOTYPE NAME TYPE FIELD CMP
131d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP
13251782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT NAME TYPE ATTR
13351782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR
13451782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE NAME TYPE ATTR
13551782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR
13651782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_FIND NAME TYPE ATTR
13751782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NFIND NAME TYPE ATTR
13851782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NEXT NAME TYPE ATTR
13951782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_PREV NAME TYPE ATTR
14051782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_MINMAX NAME TYPE ATTR
141480565d5SRuslan Ermilov.Fn RB_GENERATE NAME TYPE FIELD CMP
142d72cd779SJason Evans.Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP
14351782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR
14451782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR
14551782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE NAME TYPE FIELD ATTR
14651782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR
14751782e3aSKonstantin Belousov.Fn RB_GENERATE_FIND NAME TYPE FIELD CMP ATTR
14851782e3aSKonstantin Belousov.Fn RB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR
14951782e3aSKonstantin Belousov.Fn RB_GENERATE_NEXT NAME TYPE FIELD ATTR
15051782e3aSKonstantin Belousov.Fn RB_GENERATE_PREV NAME TYPE FIELD ATTR
15151782e3aSKonstantin Belousov.Fn RB_GENERATE_MINMAX NAME TYPE FIELD ATTR
152480565d5SRuslan Ermilov.Fn RB_ENTRY TYPE
153480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
15487f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER "RB_HEAD *head"
15587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
15687f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT "RB_HEAD *head"
15787f5f0ecSDag-Erling Smørgrav.Ft "bool"
15887f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY "RB_HEAD *head"
15987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
160480565d5SRuslan Ermilov.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm"
16187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
1628e4fd0a1SJason Evans.Fn RB_PREV NAME "RB_HEAD *head" "struct TYPE *elm"
1638e4fd0a1SJason Evans.Ft "struct TYPE *"
164480565d5SRuslan Ermilov.Fn RB_MIN NAME "RB_HEAD *head"
16587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
166480565d5SRuslan Ermilov.Fn RB_MAX NAME "RB_HEAD *head"
16787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
168480565d5SRuslan Ermilov.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm"
16987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
17006115e08SJason Evans.Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm"
17106115e08SJason Evans.Ft "struct TYPE *"
17287f5f0ecSDag-Erling Smørgrav.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME"
17387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
17487f5f0ecSDag-Erling Smørgrav.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME"
17587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
17687f5f0ecSDag-Erling Smørgrav.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
177480565d5SRuslan Ermilov.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head"
178639bf7bdSBruce M Simpson.Fn RB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME"
1799dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
1808e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head"
181639bf7bdSBruce M Simpson.Fn RB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME"
1829dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
18387f5f0ecSDag-Erling Smørgrav.Ft void
18487f5f0ecSDag-Erling Smørgrav.Fn RB_INIT "RB_HEAD *head"
18587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
186480565d5SRuslan Ermilov.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm"
18787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
188480565d5SRuslan Ermilov.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm"
18987f5f0ecSDag-Erling Smørgrav.Sh DESCRIPTION
190480565d5SRuslan ErmilovThese macros define data structures for different types of trees:
19187f5f0ecSDag-Erling Smørgravsplay trees and red-black trees.
19287f5f0ecSDag-Erling Smørgrav.Pp
19387f5f0ecSDag-Erling SmørgravIn the macro definitions,
19487f5f0ecSDag-Erling Smørgrav.Fa TYPE
19587f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must contain a field of type
196480565d5SRuslan Ermilov.Vt SPLAY_ENTRY ,
19787f5f0ecSDag-Erling Smørgravor
198480565d5SRuslan Ermilov.Vt RB_ENTRY ,
19987f5f0ecSDag-Erling Smørgravnamed
20087f5f0ecSDag-Erling Smørgrav.Fa ENTRYNAME .
20187f5f0ecSDag-Erling SmørgravThe argument
20287f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
20387f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must be declared
20487f5f0ecSDag-Erling Smørgravusing the macros
20587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD ,
20687f5f0ecSDag-Erling Smørgravor
20787f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD .
20887f5f0ecSDag-Erling SmørgravThe argument
20987f5f0ecSDag-Erling Smørgrav.Fa NAME
21087f5f0ecSDag-Erling Smørgravhas to be a unique name prefix for every tree that is defined.
21187f5f0ecSDag-Erling Smørgrav.Pp
212d72cd779SJason EvansThe function prototypes are declared with
213480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE ,
214d72cd779SJason Evans.Fn RB_PROTOTYPE ,
21587f5f0ecSDag-Erling Smørgravor
216d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC .
217d72cd779SJason EvansThe function bodies are generated with
218480565d5SRuslan Ermilov.Fn SPLAY_GENERATE ,
219d72cd779SJason Evans.Fn RB_GENERATE ,
22087f5f0ecSDag-Erling Smørgravor
221d72cd779SJason Evans.Fn RB_GENERATE_STATIC .
22287f5f0ecSDag-Erling SmørgravSee the examples below for further explanation of how these macros are used.
22387f5f0ecSDag-Erling Smørgrav.Sh SPLAY TREES
224480565d5SRuslan ErmilovA splay tree is a self-organizing data structure.
225480565d5SRuslan ErmilovEvery operation on the tree causes a splay to happen.
226480565d5SRuslan ErmilovThe splay moves the requested
22787f5f0ecSDag-Erling Smørgravnode to the root of the tree and partly rebalances it.
22887f5f0ecSDag-Erling Smørgrav.Pp
22987f5f0ecSDag-Erling SmørgravThis has the benefit that request locality causes faster lookups as
230480565d5SRuslan Ermilovthe requested nodes move to the top of the tree.
231480565d5SRuslan ErmilovOn the other hand, every lookup causes memory writes.
23287f5f0ecSDag-Erling Smørgrav.Pp
233480565d5SRuslan ErmilovThe Balance Theorem bounds the total access time for
234480565d5SRuslan Ermilov.Ar m
235480565d5SRuslan Ermilovoperations and
236480565d5SRuslan Ermilov.Ar n
237480565d5SRuslan Ermilovinserts on an initially empty tree as
238480565d5SRuslan Ermilov.Fn O "\*[lp]m + n\*[rp]lg n" .
239480565d5SRuslan ErmilovThe
240480565d5SRuslan Ermilovamortized cost for a sequence of
241480565d5SRuslan Ermilov.Ar m
242480565d5SRuslan Ermilovaccesses to a splay tree is
243480565d5SRuslan Ermilov.Fn O "lg n" .
24487f5f0ecSDag-Erling Smørgrav.Pp
24587f5f0ecSDag-Erling SmørgravA splay tree is headed by a structure defined by the
24687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD
24787f5f0ecSDag-Erling Smørgravmacro.
24887f5f0ecSDag-Erling SmørgravA
24987f5f0ecSDag-Erling Smørgravstructure is declared as follows:
250480565d5SRuslan Ermilov.Bd -ragged -offset indent
251480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
252480565d5SRuslan Ermilov.Va head ;
25387f5f0ecSDag-Erling Smørgrav.Ed
25487f5f0ecSDag-Erling Smørgrav.Pp
25587f5f0ecSDag-Erling Smørgravwhere
25687f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
25787f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct
25887f5f0ecSDag-Erling Smørgrav.Fa TYPE
25987f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree.
26087f5f0ecSDag-Erling Smørgrav.Pp
26187f5f0ecSDag-Erling SmørgravThe
26287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY
26387f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree.
26487f5f0ecSDag-Erling Smørgrav.Pp
26587f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure,
26687f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the
26787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE
26887f5f0ecSDag-Erling Smørgravmacro,
26987f5f0ecSDag-Erling Smørgravwhere
27087f5f0ecSDag-Erling Smørgrav.Fa NAME
27187f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree.
27287f5f0ecSDag-Erling SmørgravThe
27387f5f0ecSDag-Erling Smørgrav.Fa TYPE
27487f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed
27587f5f0ecSDag-Erling Smørgravby the tree.
27687f5f0ecSDag-Erling SmørgravThe
27787f5f0ecSDag-Erling Smørgrav.Fa FIELD
27887f5f0ecSDag-Erling Smørgravargument is the name of the element defined by
27987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY .
28087f5f0ecSDag-Erling Smørgrav.Pp
28187f5f0ecSDag-Erling SmørgravThe function bodies are generated with the
28287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_GENERATE
283480565d5SRuslan Ermilovmacro.
284480565d5SRuslan ErmilovIt takes the same arguments as the
28587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE
28687f5f0ecSDag-Erling Smørgravmacro, but should be used only once.
28787f5f0ecSDag-Erling Smørgrav.Pp
28887f5f0ecSDag-Erling SmørgravFinally,
28987f5f0ecSDag-Erling Smørgravthe
29087f5f0ecSDag-Erling Smørgrav.Fa CMP
291480565d5SRuslan Ermilovargument is the name of a function used to compare tree nodes
292480565d5SRuslan Ermilovwith each other.
293480565d5SRuslan ErmilovThe function takes two arguments of type
294480565d5SRuslan Ermilov.Vt "struct TYPE *" .
29587f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a
296480565d5SRuslan Ermilovvalue smaller than zero.
297480565d5SRuslan ErmilovIf they are equal, the function returns zero.
298480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero.
299480565d5SRuslan ErmilovThe compare
30087f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements.
30187f5f0ecSDag-Erling Smørgrav.Pp
30287f5f0ecSDag-Erling SmørgravThe
30387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT
30487f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by
30587f5f0ecSDag-Erling Smørgrav.Fa head .
30687f5f0ecSDag-Erling Smørgrav.Pp
30787f5f0ecSDag-Erling SmørgravThe splay tree can also be initialized statically by using the
30887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER
30987f5f0ecSDag-Erling Smørgravmacro like this:
310480565d5SRuslan Ermilov.Bd -ragged -offset indent
311480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
312480565d5SRuslan Ermilov.Va head
313480565d5SRuslan Ermilov=
314480565d5SRuslan Ermilov.Fn SPLAY_INITIALIZER &head ;
31587f5f0ecSDag-Erling Smørgrav.Ed
31687f5f0ecSDag-Erling Smørgrav.Pp
31787f5f0ecSDag-Erling SmørgravThe
31887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT
31987f5f0ecSDag-Erling Smørgravmacro inserts the new element
32087f5f0ecSDag-Erling Smørgrav.Fa elm
32187f5f0ecSDag-Erling Smørgravinto the tree.
32287f5f0ecSDag-Erling Smørgrav.Pp
32387f5f0ecSDag-Erling SmørgravThe
32487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE
32587f5f0ecSDag-Erling Smørgravmacro removes the element
32687f5f0ecSDag-Erling Smørgrav.Fa elm
32787f5f0ecSDag-Erling Smørgravfrom the tree pointed by
32887f5f0ecSDag-Erling Smørgrav.Fa head .
32987f5f0ecSDag-Erling Smørgrav.Pp
33087f5f0ecSDag-Erling SmørgravThe
33187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FIND
33287f5f0ecSDag-Erling Smørgravmacro can be used to find a particular element in the tree.
33387f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
33487f5f0ecSDag-Erling Smørgravstruct TYPE find, *res;
33587f5f0ecSDag-Erling Smørgravfind.key = 30;
33687f5f0ecSDag-Erling Smørgravres = SPLAY_FIND(NAME, head, &find);
33787f5f0ecSDag-Erling Smørgrav.Ed
33887f5f0ecSDag-Erling Smørgrav.Pp
33987f5f0ecSDag-Erling SmørgravThe
34087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT ,
34187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MIN ,
34287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MAX ,
34387f5f0ecSDag-Erling Smørgravand
34487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_NEXT
34587f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree:
34687f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
34787f5f0ecSDag-Erling Smørgravfor (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np))
34887f5f0ecSDag-Erling Smørgrav.Ed
34987f5f0ecSDag-Erling Smørgrav.Pp
35087f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the
35187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FOREACH
35287f5f0ecSDag-Erling Smørgravmacro:
353480565d5SRuslan Ermilov.Bd -ragged -offset indent
354480565d5SRuslan Ermilov.Fn SPLAY_FOREACH np NAME head
35587f5f0ecSDag-Erling Smørgrav.Ed
35687f5f0ecSDag-Erling Smørgrav.Pp
35787f5f0ecSDag-Erling SmørgravThe
35887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY
35987f5f0ecSDag-Erling Smørgravmacro should be used to check whether a splay tree is empty.
36087f5f0ecSDag-Erling Smørgrav.Sh RED-BLACK TREES
36187f5f0ecSDag-Erling SmørgravA red-black tree is a binary search tree with the node color as an
362480565d5SRuslan Ermilovextra attribute.
363480565d5SRuslan ErmilovIt fulfills a set of conditions:
364480565d5SRuslan Ermilov.Bl -enum -offset indent
36587f5f0ecSDag-Erling Smørgrav.It
366480565d5SRuslan ErmilovEvery search path from the root to a leaf consists of the same number of
367480565d5SRuslan Ermilovblack nodes.
36887f5f0ecSDag-Erling Smørgrav.It
369480565d5SRuslan ErmilovEach red node (except for the root) has a black parent.
37087f5f0ecSDag-Erling Smørgrav.It
371480565d5SRuslan ErmilovEach leaf node is black.
37287f5f0ecSDag-Erling Smørgrav.El
37387f5f0ecSDag-Erling Smørgrav.Pp
374480565d5SRuslan ErmilovEvery operation on a red-black tree is bounded as
375480565d5SRuslan Ermilov.Fn O "lg n" .
376480565d5SRuslan ErmilovThe maximum height of a red-black tree is
377480565d5SRuslan Ermilov.Fn 2lg "n + 1" .
37887f5f0ecSDag-Erling Smørgrav.Pp
37987f5f0ecSDag-Erling SmørgravA red-black tree is headed by a structure defined by the
38087f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD
38187f5f0ecSDag-Erling Smørgravmacro.
38287f5f0ecSDag-Erling SmørgravA
38387f5f0ecSDag-Erling Smørgravstructure is declared as follows:
384480565d5SRuslan Ermilov.Bd -ragged -offset indent
385480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
386480565d5SRuslan Ermilov.Va head ;
38787f5f0ecSDag-Erling Smørgrav.Ed
38887f5f0ecSDag-Erling Smørgrav.Pp
38987f5f0ecSDag-Erling Smørgravwhere
39087f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
39187f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct
39287f5f0ecSDag-Erling Smørgrav.Fa TYPE
39387f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree.
39487f5f0ecSDag-Erling Smørgrav.Pp
39587f5f0ecSDag-Erling SmørgravThe
39687f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY
39787f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree.
39887f5f0ecSDag-Erling Smørgrav.Pp
39987f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure,
40087f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the
40187f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE
402d72cd779SJason Evansor
403d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC
40487f5f0ecSDag-Erling Smørgravmacro,
40587f5f0ecSDag-Erling Smørgravwhere
40687f5f0ecSDag-Erling Smørgrav.Fa NAME
40787f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree.
40887f5f0ecSDag-Erling SmørgravThe
40987f5f0ecSDag-Erling Smørgrav.Fa TYPE
41087f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed
41187f5f0ecSDag-Erling Smørgravby the tree.
41287f5f0ecSDag-Erling SmørgravThe
41387f5f0ecSDag-Erling Smørgrav.Fa FIELD
41487f5f0ecSDag-Erling Smørgravargument is the name of the element defined by
41587f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY .
41651782e3aSKonstantin BelousovIndividual prototypes can be declared with
41751782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT ,
41851782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT_COLOR ,
41951782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE ,
42051782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE_COLOR ,
42151782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_FIND ,
42251782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NFIND ,
42351782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NEXT ,
42451782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_PREV ,
42551782e3aSKonstantin Belousovand
42651782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_MINMAX
427eb49a6d3SEdward Tomasz Napieralain case not all functions are required.
428eb49a6d3SEdward Tomasz NapieralaThe individual prototype macros expect
42951782e3aSKonstantin Belousov.Fa NAME ,
43051782e3aSKonstantin Belousov.Fa TYPE ,
43151782e3aSKonstantin Belousovand
43251782e3aSKonstantin Belousov.Fa ATTR
433eb49a6d3SEdward Tomasz Napieralaarguments.
434eb49a6d3SEdward Tomasz NapieralaThe
43551782e3aSKonstantin Belousov.Fa ATTR
43651782e3aSKonstantin Belousovargument must be empty for global functions or
43751782e3aSKonstantin Belousov.Fa static
43851782e3aSKonstantin Belousovfor static functions.
43987f5f0ecSDag-Erling Smørgrav.Pp
44087f5f0ecSDag-Erling SmørgravThe function bodies are generated with the
44187f5f0ecSDag-Erling Smørgrav.Fn RB_GENERATE
442d72cd779SJason Evansor
443d72cd779SJason Evans.Fn RB_GENERATE_STATIC
444480565d5SRuslan Ermilovmacro.
445d72cd779SJason EvansThese macros take the same arguments as the
44687f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE
447d72cd779SJason Evansand
448d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC
449d72cd779SJason Evansmacros, but should be used only once.
45051782e3aSKonstantin BelousovAs an alternative individual function bodies are generated with the
45151782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT ,
45251782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT_COLOR ,
45351782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE ,
45451782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE_COLOR ,
45551782e3aSKonstantin Belousov.Fn RB_GENERATE_FIND ,
45651782e3aSKonstantin Belousov.Fn RB_GENERATE_NFIND ,
45751782e3aSKonstantin Belousov.Fn RB_GENERATE_NEXT ,
45851782e3aSKonstantin Belousov.Fn RB_GENERATE_PREV ,
45951782e3aSKonstantin Belousovand
46051782e3aSKonstantin Belousov.Fn RB_GENERATE_MINMAX
46151782e3aSKonstantin Belousovmacros.
46287f5f0ecSDag-Erling Smørgrav.Pp
46387f5f0ecSDag-Erling SmørgravFinally,
46487f5f0ecSDag-Erling Smørgravthe
46587f5f0ecSDag-Erling Smørgrav.Fa CMP
4669d44cd42SBenno Riceargument is the name of a function used to compare tree nodes
467480565d5SRuslan Ermilovwith each other.
468480565d5SRuslan ErmilovThe function takes two arguments of type
469480565d5SRuslan Ermilov.Vt "struct TYPE *" .
47087f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a
471480565d5SRuslan Ermilovvalue smaller than zero.
472480565d5SRuslan ErmilovIf they are equal, the function returns zero.
473480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero.
474480565d5SRuslan ErmilovThe compare
47587f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements.
47687f5f0ecSDag-Erling Smørgrav.Pp
47787f5f0ecSDag-Erling SmørgravThe
47887f5f0ecSDag-Erling Smørgrav.Fn RB_INIT
47987f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by
48087f5f0ecSDag-Erling Smørgrav.Fa head .
48187f5f0ecSDag-Erling Smørgrav.Pp
4823b96c71fSMike PritchardThe red-black tree can also be initialized statically by using the
48387f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER
48487f5f0ecSDag-Erling Smørgravmacro like this:
485480565d5SRuslan Ermilov.Bd -ragged -offset indent
486480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
487480565d5SRuslan Ermilov.Va head
488480565d5SRuslan Ermilov=
489480565d5SRuslan Ermilov.Fn RB_INITIALIZER &head ;
49087f5f0ecSDag-Erling Smørgrav.Ed
49187f5f0ecSDag-Erling Smørgrav.Pp
49287f5f0ecSDag-Erling SmørgravThe
49387f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT
49487f5f0ecSDag-Erling Smørgravmacro inserts the new element
49587f5f0ecSDag-Erling Smørgrav.Fa elm
49687f5f0ecSDag-Erling Smørgravinto the tree.
49787f5f0ecSDag-Erling Smørgrav.Pp
49887f5f0ecSDag-Erling SmørgravThe
49987f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE
50087f5f0ecSDag-Erling Smørgravmacro removes the element
50187f5f0ecSDag-Erling Smørgrav.Fa elm
50287f5f0ecSDag-Erling Smørgravfrom the tree pointed by
50387f5f0ecSDag-Erling Smørgrav.Fa head .
50487f5f0ecSDag-Erling Smørgrav.Pp
50587f5f0ecSDag-Erling SmørgravThe
50687f5f0ecSDag-Erling Smørgrav.Fn RB_FIND
50706115e08SJason Evansand
50806115e08SJason Evans.Fn RB_NFIND
50906115e08SJason Evansmacros can be used to find a particular element in the tree.
51087f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
51187f5f0ecSDag-Erling Smørgravstruct TYPE find, *res;
51287f5f0ecSDag-Erling Smørgravfind.key = 30;
51387f5f0ecSDag-Erling Smørgravres = RB_FIND(NAME, head, &find);
51487f5f0ecSDag-Erling Smørgrav.Ed
51587f5f0ecSDag-Erling Smørgrav.Pp
51687f5f0ecSDag-Erling SmørgravThe
51787f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT ,
51887f5f0ecSDag-Erling Smørgrav.Fn RB_MIN ,
51987f5f0ecSDag-Erling Smørgrav.Fn RB_MAX ,
5208e4fd0a1SJason Evans.Fn RB_NEXT ,
52187f5f0ecSDag-Erling Smørgravand
5228e4fd0a1SJason Evans.Fn RB_PREV
52387f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree:
524480565d5SRuslan Ermilov.Pp
525480565d5SRuslan Ermilov.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))"
52687f5f0ecSDag-Erling Smørgrav.Pp
52787f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the
52887f5f0ecSDag-Erling Smørgrav.Fn RB_FOREACH
5298e4fd0a1SJason Evansor
5308e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE
53187f5f0ecSDag-Erling Smørgravmacro:
532480565d5SRuslan Ermilov.Bd -ragged -offset indent
533480565d5SRuslan Ermilov.Fn RB_FOREACH np NAME head
53487f5f0ecSDag-Erling Smørgrav.Ed
53587f5f0ecSDag-Erling Smørgrav.Pp
5369dbae282SGleb SmirnoffThe macros
5379dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE
5389dbae282SGleb Smirnoffand
5399dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE
5409dbae282SGleb Smirnofftraverse the tree referenced by head
5419dbae282SGleb Smirnoffin a forward or reverse direction respectively,
5429dbae282SGleb Smirnoffassigning each element in turn to np.
5439dbae282SGleb SmirnoffHowever, unlike their unsafe counterparts,
5449dbae282SGleb Smirnoffthey permit both the removal of np
5459dbae282SGleb Smirnoffas well as freeing it from within the loop safely
5469dbae282SGleb Smirnoffwithout interfering with the traversal.
5479dbae282SGleb Smirnoff.Pp
548bff27689SBruce M SimpsonBoth
549bff27689SBruce M Simpson.Fn RB_FOREACH_FROM
550bff27689SBruce M Simpsonand
551bff27689SBruce M Simpson.Fn RB_FOREACH_REVERSE_FROM
552bff27689SBruce M Simpsonmay be used to continue an interrupted traversal
553bff27689SBruce M Simpsonin a forward or reverse direction respectively.
554639bf7bdSBruce M SimpsonThe head pointer is not required.
555639bf7bdSBruce M SimpsonThe pointer to the node from where to resume the traversal
556639bf7bdSBruce M Simpsonshould be passed as their last argument,
557bff27689SBruce M Simpsonand will be overwritten to provide safe traversal.
558bff27689SBruce M Simpson.Pp
55987f5f0ecSDag-Erling SmørgravThe
56087f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY
561309e4b9bSDag-Erling Smørgravmacro should be used to check whether a red-black tree is empty.
562ac0879c3SEdward Tomasz Napierala.Sh EXAMPLES
563ac0879c3SEdward Tomasz NapieralaThe following example demonstrates how to declare a red-black tree
564ac0879c3SEdward Tomasz Napieralaholding integers.
565ac0879c3SEdward Tomasz NapieralaValues are inserted into it and the contents of the tree are printed
566ac0879c3SEdward Tomasz Napieralain order.
567ac0879c3SEdward Tomasz NapieralaLastly, the internal structure of the tree is printed.
568ac0879c3SEdward Tomasz Napierala.Bd -literal -offset 3n
569ac0879c3SEdward Tomasz Napierala#include <sys/tree.h>
570ac0879c3SEdward Tomasz Napierala#include <err.h>
571ac0879c3SEdward Tomasz Napierala#include <stdio.h>
572ac0879c3SEdward Tomasz Napierala#include <stdlib.h>
573ac0879c3SEdward Tomasz Napierala
574ac0879c3SEdward Tomasz Napieralastruct node {
575ac0879c3SEdward Tomasz Napierala	RB_ENTRY(node) entry;
576ac0879c3SEdward Tomasz Napierala	int i;
577ac0879c3SEdward Tomasz Napierala};
578ac0879c3SEdward Tomasz Napierala
579ac0879c3SEdward Tomasz Napieralaint
580ac0879c3SEdward Tomasz Napieralaintcmp(struct node *e1, struct node *e2)
581ac0879c3SEdward Tomasz Napierala{
582ac0879c3SEdward Tomasz Napierala	return (e1->i < e2->i ? -1 : e1->i > e2->i);
583ac0879c3SEdward Tomasz Napierala}
584ac0879c3SEdward Tomasz Napierala
585ac0879c3SEdward Tomasz NapieralaRB_HEAD(inttree, node) head = RB_INITIALIZER(&head);
586ac0879c3SEdward Tomasz NapieralaRB_GENERATE(inttree, node, entry, intcmp)
587ac0879c3SEdward Tomasz Napierala
588ac0879c3SEdward Tomasz Napieralaint testdata[] = {
589ac0879c3SEdward Tomasz Napierala	20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18,
590ac0879c3SEdward Tomasz Napierala	7, 11, 14
591ac0879c3SEdward Tomasz Napierala};
592ac0879c3SEdward Tomasz Napierala
593ac0879c3SEdward Tomasz Napieralavoid
594ac0879c3SEdward Tomasz Napieralaprint_tree(struct node *n)
595ac0879c3SEdward Tomasz Napierala{
596ac0879c3SEdward Tomasz Napierala	struct node *left, *right;
597ac0879c3SEdward Tomasz Napierala
598ac0879c3SEdward Tomasz Napierala	if (n == NULL) {
599ac0879c3SEdward Tomasz Napierala		printf("nil");
600ac0879c3SEdward Tomasz Napierala		return;
601ac0879c3SEdward Tomasz Napierala	}
602ac0879c3SEdward Tomasz Napierala	left = RB_LEFT(n, entry);
603ac0879c3SEdward Tomasz Napierala	right = RB_RIGHT(n, entry);
604ac0879c3SEdward Tomasz Napierala	if (left == NULL && right == NULL)
605ac0879c3SEdward Tomasz Napierala		printf("%d", n->i);
606ac0879c3SEdward Tomasz Napierala	else {
607ac0879c3SEdward Tomasz Napierala		printf("%d(", n->i);
608ac0879c3SEdward Tomasz Napierala		print_tree(left);
609ac0879c3SEdward Tomasz Napierala		printf(",");
610ac0879c3SEdward Tomasz Napierala		print_tree(right);
611ac0879c3SEdward Tomasz Napierala		printf(")");
612ac0879c3SEdward Tomasz Napierala	}
613ac0879c3SEdward Tomasz Napierala}
614ac0879c3SEdward Tomasz Napierala
615ac0879c3SEdward Tomasz Napieralaint
616ac0879c3SEdward Tomasz Napieralamain(void)
617ac0879c3SEdward Tomasz Napierala{
618ac0879c3SEdward Tomasz Napierala	int i;
619ac0879c3SEdward Tomasz Napierala	struct node *n;
620ac0879c3SEdward Tomasz Napierala
621ac0879c3SEdward Tomasz Napierala	for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) {
622ac0879c3SEdward Tomasz Napierala		if ((n = malloc(sizeof(struct node))) == NULL)
623ac0879c3SEdward Tomasz Napierala			err(1, NULL);
624ac0879c3SEdward Tomasz Napierala		n->i = testdata[i];
625ac0879c3SEdward Tomasz Napierala		RB_INSERT(inttree, &head, n);
626ac0879c3SEdward Tomasz Napierala	}
627ac0879c3SEdward Tomasz Napierala
628ac0879c3SEdward Tomasz Napierala	RB_FOREACH(n, inttree, &head) {
629ac0879c3SEdward Tomasz Napierala		printf("%d\en", n->i);
630ac0879c3SEdward Tomasz Napierala	}
631ac0879c3SEdward Tomasz Napierala	print_tree(RB_ROOT(&head));
632ac0879c3SEdward Tomasz Napierala	printf("\en");
633ac0879c3SEdward Tomasz Napierala	return (0);
634ac0879c3SEdward Tomasz Napierala}
635ac0879c3SEdward Tomasz Napierala.Ed
63687f5f0ecSDag-Erling Smørgrav.Sh NOTES
63787f5f0ecSDag-Erling SmørgravTrying to free a tree in the following way is a common error:
63887f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
63987f5f0ecSDag-Erling SmørgravSPLAY_FOREACH(var, NAME, head) {
64087f5f0ecSDag-Erling Smørgrav	SPLAY_REMOVE(NAME, head, var);
64187f5f0ecSDag-Erling Smørgrav	free(var);
64287f5f0ecSDag-Erling Smørgrav}
64387f5f0ecSDag-Erling Smørgravfree(head);
64487f5f0ecSDag-Erling Smørgrav.Ed
64587f5f0ecSDag-Erling Smørgrav.Pp
64687f5f0ecSDag-Erling SmørgravSince
64787f5f0ecSDag-Erling Smørgrav.Va var
648480565d5SRuslan Ermilovis freed, the
64987f5f0ecSDag-Erling Smørgrav.Fn FOREACH
65087f5f0ecSDag-Erling Smørgravmacro refers to a pointer that may have been reallocated already.
65187f5f0ecSDag-Erling SmørgravProper code needs a second variable.
65287f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
65387f5f0ecSDag-Erling Smørgravfor (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) {
65487f5f0ecSDag-Erling Smørgrav	nxt = SPLAY_NEXT(NAME, head, var);
65587f5f0ecSDag-Erling Smørgrav	SPLAY_REMOVE(NAME, head, var);
65687f5f0ecSDag-Erling Smørgrav	free(var);
65787f5f0ecSDag-Erling Smørgrav}
65887f5f0ecSDag-Erling Smørgrav.Ed
65987f5f0ecSDag-Erling Smørgrav.Pp
66087f5f0ecSDag-Erling SmørgravBoth
66187f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT
66287f5f0ecSDag-Erling Smørgravand
66387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT
66487f5f0ecSDag-Erling Smørgravreturn
665480565d5SRuslan Ermilov.Dv NULL
66687f5f0ecSDag-Erling Smørgravif the element was inserted in the tree successfully, otherwise they
66787f5f0ecSDag-Erling Smørgravreturn a pointer to the element with the colliding key.
66887f5f0ecSDag-Erling Smørgrav.Pp
66987f5f0ecSDag-Erling SmørgravAccordingly,
67087f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE
67187f5f0ecSDag-Erling Smørgravand
67287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE
67387f5f0ecSDag-Erling Smørgravreturn the pointer to the removed element otherwise they return
674480565d5SRuslan Ermilov.Dv NULL
67587f5f0ecSDag-Erling Smørgravto indicate an error.
676b9ec8f3bSSimon L. B. Nielsen.Sh SEE ALSO
677*fad4b12bSEdward Tomasz Napierala.Xr arb 3 ,
678b9ec8f3bSSimon L. B. Nielsen.Xr queue 3
67987f5f0ecSDag-Erling Smørgrav.Sh AUTHORS
680480565d5SRuslan ErmilovThe author of the tree macros is
681480565d5SRuslan Ermilov.An Niels Provos .
682