xref: /freebsd/share/man/man3/tree.3 (revision 757a04bf824d8d12f970ce79b5c816b2c3a571e7)
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.\"
33*757a04bfSSergio Carlavilla Delgado.Dd February 25, 2020
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 ,
6522823764SEdward Tomasz Napierala.Nm RB_PROTOTYPE_REINSERT ,
6687f5f0ecSDag-Erling Smørgrav.Nm RB_GENERATE ,
67d72cd779SJason Evans.Nm RB_GENERATE_STATIC ,
6851782e3aSKonstantin Belousov.Nm RB_GENERATE_INSERT ,
6951782e3aSKonstantin Belousov.Nm RB_GENERATE_INSERT_COLOR ,
7051782e3aSKonstantin Belousov.Nm RB_GENERATE_REMOVE ,
7151782e3aSKonstantin Belousov.Nm RB_GENERATE_REMOVE_COLOR ,
7251782e3aSKonstantin Belousov.Nm RB_GENERATE_FIND ,
7351782e3aSKonstantin Belousov.Nm RB_GENERATE_NFIND ,
7451782e3aSKonstantin Belousov.Nm RB_GENERATE_NEXT ,
7551782e3aSKonstantin Belousov.Nm RB_GENERATE_PREV ,
7651782e3aSKonstantin Belousov.Nm RB_GENERATE_MINMAX ,
7722823764SEdward Tomasz Napierala.Nm RB_GENERATE_REINSERT ,
7887f5f0ecSDag-Erling Smørgrav.Nm RB_ENTRY ,
7987f5f0ecSDag-Erling Smørgrav.Nm RB_HEAD ,
8087f5f0ecSDag-Erling Smørgrav.Nm RB_INITIALIZER ,
8187f5f0ecSDag-Erling Smørgrav.Nm RB_ROOT ,
8287f5f0ecSDag-Erling Smørgrav.Nm RB_EMPTY ,
8387f5f0ecSDag-Erling Smørgrav.Nm RB_NEXT ,
848e4fd0a1SJason Evans.Nm RB_PREV ,
8587f5f0ecSDag-Erling Smørgrav.Nm RB_MIN ,
8687f5f0ecSDag-Erling Smørgrav.Nm RB_MAX ,
8787f5f0ecSDag-Erling Smørgrav.Nm RB_FIND ,
8806115e08SJason Evans.Nm RB_NFIND ,
8987f5f0ecSDag-Erling Smørgrav.Nm RB_LEFT ,
9087f5f0ecSDag-Erling Smørgrav.Nm RB_RIGHT ,
9187f5f0ecSDag-Erling Smørgrav.Nm RB_PARENT ,
9287f5f0ecSDag-Erling Smørgrav.Nm RB_FOREACH ,
93bff27689SBruce M Simpson.Nm RB_FOREACH_FROM ,
949dbae282SGleb Smirnoff.Nm RB_FOREACH_SAFE ,
958e4fd0a1SJason Evans.Nm RB_FOREACH_REVERSE ,
96bff27689SBruce M Simpson.Nm RB_FOREACH_REVERSE_FROM ,
979dbae282SGleb Smirnoff.Nm RB_FOREACH_REVERSE_SAFE ,
9887f5f0ecSDag-Erling Smørgrav.Nm RB_INIT ,
9987f5f0ecSDag-Erling Smørgrav.Nm RB_INSERT ,
10022823764SEdward Tomasz Napierala.Nm RB_REMOVE ,
10122823764SEdward Tomasz Napierala.Nm RB_REINSERT
10287f5f0ecSDag-Erling Smørgrav.Nd "implementations of splay and red-black trees"
10387f5f0ecSDag-Erling Smørgrav.Sh SYNOPSIS
104480565d5SRuslan Ermilov.In sys/tree.h
105480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP
106480565d5SRuslan Ermilov.Fn SPLAY_GENERATE NAME TYPE FIELD CMP
107480565d5SRuslan Ermilov.Fn SPLAY_ENTRY TYPE
108480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
10987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
11087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head"
11187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT "SPLAY_HEAD *head"
112480565d5SRuslan Ermilov.Ft bool
11387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY "SPLAY_HEAD *head"
11487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
115480565d5SRuslan Ermilov.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
11687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
117480565d5SRuslan Ermilov.Fn SPLAY_MIN NAME "SPLAY_HEAD *head"
11887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
119480565d5SRuslan Ermilov.Fn SPLAY_MAX NAME "SPLAY_HEAD *head"
12087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
121480565d5SRuslan Ermilov.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm"
12287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
12387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME"
12487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
12587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME"
126480565d5SRuslan Ermilov.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head"
12787f5f0ecSDag-Erling Smørgrav.Ft void
12887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT "SPLAY_HEAD *head"
12987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
130480565d5SRuslan Ermilov.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
13187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
132480565d5SRuslan Ermilov.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm"
133480565d5SRuslan Ermilov.Fn RB_PROTOTYPE NAME TYPE FIELD CMP
134d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP
13551782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT NAME TYPE ATTR
13651782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR
13751782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE NAME TYPE ATTR
13851782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR
13951782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_FIND NAME TYPE ATTR
14051782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NFIND NAME TYPE ATTR
14151782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NEXT NAME TYPE ATTR
14251782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_PREV NAME TYPE ATTR
14351782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_MINMAX NAME TYPE ATTR
14422823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_REINSERT NAME TYPE ATTR
145480565d5SRuslan Ermilov.Fn RB_GENERATE NAME TYPE FIELD CMP
146d72cd779SJason Evans.Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP
14751782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR
14851782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR
14951782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE NAME TYPE FIELD ATTR
15051782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR
15151782e3aSKonstantin Belousov.Fn RB_GENERATE_FIND NAME TYPE FIELD CMP ATTR
15251782e3aSKonstantin Belousov.Fn RB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR
15351782e3aSKonstantin Belousov.Fn RB_GENERATE_NEXT NAME TYPE FIELD ATTR
15451782e3aSKonstantin Belousov.Fn RB_GENERATE_PREV NAME TYPE FIELD ATTR
15551782e3aSKonstantin Belousov.Fn RB_GENERATE_MINMAX NAME TYPE FIELD ATTR
15622823764SEdward Tomasz Napierala.Fn RB_GENERATE_REINSERT NAME TYPE FIELD CMP ATTR
157480565d5SRuslan Ermilov.Fn RB_ENTRY TYPE
158480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
15987f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER "RB_HEAD *head"
16087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
16187f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT "RB_HEAD *head"
16287f5f0ecSDag-Erling Smørgrav.Ft "bool"
16387f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY "RB_HEAD *head"
16487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
165480565d5SRuslan Ermilov.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm"
16687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
1678e4fd0a1SJason Evans.Fn RB_PREV NAME "RB_HEAD *head" "struct TYPE *elm"
1688e4fd0a1SJason Evans.Ft "struct TYPE *"
169480565d5SRuslan Ermilov.Fn RB_MIN NAME "RB_HEAD *head"
17087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
171480565d5SRuslan Ermilov.Fn RB_MAX NAME "RB_HEAD *head"
17287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
173480565d5SRuslan Ermilov.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm"
17487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
17506115e08SJason Evans.Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm"
17606115e08SJason Evans.Ft "struct TYPE *"
17787f5f0ecSDag-Erling Smørgrav.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME"
17887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
17987f5f0ecSDag-Erling Smørgrav.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME"
18087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
18187f5f0ecSDag-Erling Smørgrav.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
182480565d5SRuslan Ermilov.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head"
183639bf7bdSBruce M Simpson.Fn RB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME"
1849dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
1858e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head"
186639bf7bdSBruce M Simpson.Fn RB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME"
1879dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
18887f5f0ecSDag-Erling Smørgrav.Ft void
18987f5f0ecSDag-Erling Smørgrav.Fn RB_INIT "RB_HEAD *head"
19087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
191480565d5SRuslan Ermilov.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm"
19287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
193480565d5SRuslan Ermilov.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm"
19422823764SEdward Tomasz Napierala.Ft "struct TYPE *"
19522823764SEdward Tomasz Napierala.Fn RB_REINSERT NAME "RB_HEAD *head" "struct TYPE *elm"
19687f5f0ecSDag-Erling Smørgrav.Sh DESCRIPTION
197480565d5SRuslan ErmilovThese macros define data structures for different types of trees:
19887f5f0ecSDag-Erling Smørgravsplay trees and red-black trees.
19987f5f0ecSDag-Erling Smørgrav.Pp
20087f5f0ecSDag-Erling SmørgravIn the macro definitions,
20187f5f0ecSDag-Erling Smørgrav.Fa TYPE
20287f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must contain a field of type
203480565d5SRuslan Ermilov.Vt SPLAY_ENTRY ,
20487f5f0ecSDag-Erling Smørgravor
205480565d5SRuslan Ermilov.Vt RB_ENTRY ,
20687f5f0ecSDag-Erling Smørgravnamed
20787f5f0ecSDag-Erling Smørgrav.Fa ENTRYNAME .
20887f5f0ecSDag-Erling SmørgravThe argument
20987f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
21087f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must be declared
21187f5f0ecSDag-Erling Smørgravusing the macros
21287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD ,
21387f5f0ecSDag-Erling Smørgravor
21487f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD .
21587f5f0ecSDag-Erling SmørgravThe argument
21687f5f0ecSDag-Erling Smørgrav.Fa NAME
21787f5f0ecSDag-Erling Smørgravhas to be a unique name prefix for every tree that is defined.
21887f5f0ecSDag-Erling Smørgrav.Pp
219d72cd779SJason EvansThe function prototypes are declared with
220480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE ,
221d72cd779SJason Evans.Fn RB_PROTOTYPE ,
22287f5f0ecSDag-Erling Smørgravor
223d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC .
224d72cd779SJason EvansThe function bodies are generated with
225480565d5SRuslan Ermilov.Fn SPLAY_GENERATE ,
226d72cd779SJason Evans.Fn RB_GENERATE ,
22787f5f0ecSDag-Erling Smørgravor
228d72cd779SJason Evans.Fn RB_GENERATE_STATIC .
22987f5f0ecSDag-Erling SmørgravSee the examples below for further explanation of how these macros are used.
23087f5f0ecSDag-Erling Smørgrav.Sh SPLAY TREES
231480565d5SRuslan ErmilovA splay tree is a self-organizing data structure.
232480565d5SRuslan ErmilovEvery operation on the tree causes a splay to happen.
233480565d5SRuslan ErmilovThe splay moves the requested
23487f5f0ecSDag-Erling Smørgravnode to the root of the tree and partly rebalances it.
23587f5f0ecSDag-Erling Smørgrav.Pp
23687f5f0ecSDag-Erling SmørgravThis has the benefit that request locality causes faster lookups as
237480565d5SRuslan Ermilovthe requested nodes move to the top of the tree.
238480565d5SRuslan ErmilovOn the other hand, every lookup causes memory writes.
23987f5f0ecSDag-Erling Smørgrav.Pp
240480565d5SRuslan ErmilovThe Balance Theorem bounds the total access time for
241480565d5SRuslan Ermilov.Ar m
242480565d5SRuslan Ermilovoperations and
243480565d5SRuslan Ermilov.Ar n
244480565d5SRuslan Ermilovinserts on an initially empty tree as
245480565d5SRuslan Ermilov.Fn O "\*[lp]m + n\*[rp]lg n" .
246480565d5SRuslan ErmilovThe
247480565d5SRuslan Ermilovamortized cost for a sequence of
248480565d5SRuslan Ermilov.Ar m
249480565d5SRuslan Ermilovaccesses to a splay tree is
250480565d5SRuslan Ermilov.Fn O "lg n" .
25187f5f0ecSDag-Erling Smørgrav.Pp
25287f5f0ecSDag-Erling SmørgravA splay tree is headed by a structure defined by the
25387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD
25487f5f0ecSDag-Erling Smørgravmacro.
25587f5f0ecSDag-Erling SmørgravA
25687f5f0ecSDag-Erling Smørgravstructure is declared as follows:
257480565d5SRuslan Ermilov.Bd -ragged -offset indent
258480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
259480565d5SRuslan Ermilov.Va head ;
26087f5f0ecSDag-Erling Smørgrav.Ed
26187f5f0ecSDag-Erling Smørgrav.Pp
26287f5f0ecSDag-Erling Smørgravwhere
26387f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
26487f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct
26587f5f0ecSDag-Erling Smørgrav.Fa TYPE
26687f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree.
26787f5f0ecSDag-Erling Smørgrav.Pp
26887f5f0ecSDag-Erling SmørgravThe
26987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY
27087f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree.
27187f5f0ecSDag-Erling Smørgrav.Pp
27287f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure,
27387f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the
27487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE
27587f5f0ecSDag-Erling Smørgravmacro,
27687f5f0ecSDag-Erling Smørgravwhere
27787f5f0ecSDag-Erling Smørgrav.Fa NAME
27887f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree.
27987f5f0ecSDag-Erling SmørgravThe
28087f5f0ecSDag-Erling Smørgrav.Fa TYPE
28187f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed
28287f5f0ecSDag-Erling Smørgravby the tree.
28387f5f0ecSDag-Erling SmørgravThe
28487f5f0ecSDag-Erling Smørgrav.Fa FIELD
28587f5f0ecSDag-Erling Smørgravargument is the name of the element defined by
28687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY .
28787f5f0ecSDag-Erling Smørgrav.Pp
28887f5f0ecSDag-Erling SmørgravThe function bodies are generated with the
28987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_GENERATE
290480565d5SRuslan Ermilovmacro.
291480565d5SRuslan ErmilovIt takes the same arguments as the
29287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE
29387f5f0ecSDag-Erling Smørgravmacro, but should be used only once.
29487f5f0ecSDag-Erling Smørgrav.Pp
29587f5f0ecSDag-Erling SmørgravFinally,
29687f5f0ecSDag-Erling Smørgravthe
29787f5f0ecSDag-Erling Smørgrav.Fa CMP
298480565d5SRuslan Ermilovargument is the name of a function used to compare tree nodes
299480565d5SRuslan Ermilovwith each other.
300480565d5SRuslan ErmilovThe function takes two arguments of type
301480565d5SRuslan Ermilov.Vt "struct TYPE *" .
30287f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a
303480565d5SRuslan Ermilovvalue smaller than zero.
304480565d5SRuslan ErmilovIf they are equal, the function returns zero.
305480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero.
306480565d5SRuslan ErmilovThe compare
30787f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements.
30887f5f0ecSDag-Erling Smørgrav.Pp
30987f5f0ecSDag-Erling SmørgravThe
31087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT
31187f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by
31287f5f0ecSDag-Erling Smørgrav.Fa head .
31387f5f0ecSDag-Erling Smørgrav.Pp
31487f5f0ecSDag-Erling SmørgravThe splay tree can also be initialized statically by using the
31587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER
31687f5f0ecSDag-Erling Smørgravmacro like this:
317480565d5SRuslan Ermilov.Bd -ragged -offset indent
318480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
319480565d5SRuslan Ermilov.Va head
320480565d5SRuslan Ermilov=
321480565d5SRuslan Ermilov.Fn SPLAY_INITIALIZER &head ;
32287f5f0ecSDag-Erling Smørgrav.Ed
32387f5f0ecSDag-Erling Smørgrav.Pp
32487f5f0ecSDag-Erling SmørgravThe
32587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT
32687f5f0ecSDag-Erling Smørgravmacro inserts the new element
32787f5f0ecSDag-Erling Smørgrav.Fa elm
32887f5f0ecSDag-Erling Smørgravinto the tree.
32987f5f0ecSDag-Erling Smørgrav.Pp
33087f5f0ecSDag-Erling SmørgravThe
33187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE
33287f5f0ecSDag-Erling Smørgravmacro removes the element
33387f5f0ecSDag-Erling Smørgrav.Fa elm
33487f5f0ecSDag-Erling Smørgravfrom the tree pointed by
33587f5f0ecSDag-Erling Smørgrav.Fa head .
33687f5f0ecSDag-Erling Smørgrav.Pp
33787f5f0ecSDag-Erling SmørgravThe
33887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FIND
33987f5f0ecSDag-Erling Smørgravmacro can be used to find a particular element in the tree.
34087f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
34187f5f0ecSDag-Erling Smørgravstruct TYPE find, *res;
34287f5f0ecSDag-Erling Smørgravfind.key = 30;
34387f5f0ecSDag-Erling Smørgravres = SPLAY_FIND(NAME, head, &find);
34487f5f0ecSDag-Erling Smørgrav.Ed
34587f5f0ecSDag-Erling Smørgrav.Pp
34687f5f0ecSDag-Erling SmørgravThe
34787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT ,
34887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MIN ,
34987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MAX ,
35087f5f0ecSDag-Erling Smørgravand
35187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_NEXT
35287f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree:
35387f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
35487f5f0ecSDag-Erling Smørgravfor (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np))
35587f5f0ecSDag-Erling Smørgrav.Ed
35687f5f0ecSDag-Erling Smørgrav.Pp
35787f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the
35887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FOREACH
35987f5f0ecSDag-Erling Smørgravmacro:
360480565d5SRuslan Ermilov.Bd -ragged -offset indent
361480565d5SRuslan Ermilov.Fn SPLAY_FOREACH np NAME head
36287f5f0ecSDag-Erling Smørgrav.Ed
36387f5f0ecSDag-Erling Smørgrav.Pp
36487f5f0ecSDag-Erling SmørgravThe
36587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY
36687f5f0ecSDag-Erling Smørgravmacro should be used to check whether a splay tree is empty.
36787f5f0ecSDag-Erling Smørgrav.Sh RED-BLACK TREES
36887f5f0ecSDag-Erling SmørgravA red-black tree is a binary search tree with the node color as an
369480565d5SRuslan Ermilovextra attribute.
370480565d5SRuslan ErmilovIt fulfills a set of conditions:
371480565d5SRuslan Ermilov.Bl -enum -offset indent
37287f5f0ecSDag-Erling Smørgrav.It
373480565d5SRuslan ErmilovEvery search path from the root to a leaf consists of the same number of
374480565d5SRuslan Ermilovblack nodes.
37587f5f0ecSDag-Erling Smørgrav.It
376480565d5SRuslan ErmilovEach red node (except for the root) has a black parent.
37787f5f0ecSDag-Erling Smørgrav.It
378480565d5SRuslan ErmilovEach leaf node is black.
37987f5f0ecSDag-Erling Smørgrav.El
38087f5f0ecSDag-Erling Smørgrav.Pp
381480565d5SRuslan ErmilovEvery operation on a red-black tree is bounded as
382480565d5SRuslan Ermilov.Fn O "lg n" .
383480565d5SRuslan ErmilovThe maximum height of a red-black tree is
384480565d5SRuslan Ermilov.Fn 2lg "n + 1" .
38587f5f0ecSDag-Erling Smørgrav.Pp
38687f5f0ecSDag-Erling SmørgravA red-black tree is headed by a structure defined by the
38787f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD
38887f5f0ecSDag-Erling Smørgravmacro.
38987f5f0ecSDag-Erling SmørgravA
39087f5f0ecSDag-Erling Smørgravstructure is declared as follows:
391480565d5SRuslan Ermilov.Bd -ragged -offset indent
392480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
393480565d5SRuslan Ermilov.Va head ;
39487f5f0ecSDag-Erling Smørgrav.Ed
39587f5f0ecSDag-Erling Smørgrav.Pp
39687f5f0ecSDag-Erling Smørgravwhere
39787f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
39887f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct
39987f5f0ecSDag-Erling Smørgrav.Fa TYPE
40087f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree.
40187f5f0ecSDag-Erling Smørgrav.Pp
40287f5f0ecSDag-Erling SmørgravThe
40387f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY
40487f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree.
40587f5f0ecSDag-Erling Smørgrav.Pp
40687f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure,
40787f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the
40887f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE
409d72cd779SJason Evansor
410d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC
41187f5f0ecSDag-Erling Smørgravmacro,
41287f5f0ecSDag-Erling Smørgravwhere
41387f5f0ecSDag-Erling Smørgrav.Fa NAME
41487f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree.
41587f5f0ecSDag-Erling SmørgravThe
41687f5f0ecSDag-Erling Smørgrav.Fa TYPE
41787f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed
41887f5f0ecSDag-Erling Smørgravby the tree.
41987f5f0ecSDag-Erling SmørgravThe
42087f5f0ecSDag-Erling Smørgrav.Fa FIELD
42187f5f0ecSDag-Erling Smørgravargument is the name of the element defined by
42287f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY .
42351782e3aSKonstantin BelousovIndividual prototypes can be declared with
42451782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT ,
42551782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT_COLOR ,
42651782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE ,
42751782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE_COLOR ,
42851782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_FIND ,
42951782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NFIND ,
43051782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NEXT ,
43151782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_PREV ,
43222823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_MINMAX ,
43351782e3aSKonstantin Belousovand
43422823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_REINSERT
435eb49a6d3SEdward Tomasz Napieralain case not all functions are required.
436eb49a6d3SEdward Tomasz NapieralaThe individual prototype macros expect
43751782e3aSKonstantin Belousov.Fa NAME ,
43851782e3aSKonstantin Belousov.Fa TYPE ,
43951782e3aSKonstantin Belousovand
44051782e3aSKonstantin Belousov.Fa ATTR
441eb49a6d3SEdward Tomasz Napieralaarguments.
442eb49a6d3SEdward Tomasz NapieralaThe
44351782e3aSKonstantin Belousov.Fa ATTR
44451782e3aSKonstantin Belousovargument must be empty for global functions or
44551782e3aSKonstantin Belousov.Fa static
44651782e3aSKonstantin Belousovfor static functions.
44787f5f0ecSDag-Erling Smørgrav.Pp
44887f5f0ecSDag-Erling SmørgravThe function bodies are generated with the
44987f5f0ecSDag-Erling Smørgrav.Fn RB_GENERATE
450d72cd779SJason Evansor
451d72cd779SJason Evans.Fn RB_GENERATE_STATIC
452480565d5SRuslan Ermilovmacro.
453d72cd779SJason EvansThese macros take the same arguments as the
45487f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE
455d72cd779SJason Evansand
456d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC
457d72cd779SJason Evansmacros, but should be used only once.
45851782e3aSKonstantin BelousovAs an alternative individual function bodies are generated with the
45951782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT ,
46051782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT_COLOR ,
46151782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE ,
46251782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE_COLOR ,
46351782e3aSKonstantin Belousov.Fn RB_GENERATE_FIND ,
46451782e3aSKonstantin Belousov.Fn RB_GENERATE_NFIND ,
46551782e3aSKonstantin Belousov.Fn RB_GENERATE_NEXT ,
46651782e3aSKonstantin Belousov.Fn RB_GENERATE_PREV ,
46722823764SEdward Tomasz Napierala.Fn RB_GENERATE_MINMAX ,
46851782e3aSKonstantin Belousovand
46922823764SEdward Tomasz Napierala.Fn RB_GENERATE_REINSERT
47051782e3aSKonstantin Belousovmacros.
47187f5f0ecSDag-Erling Smørgrav.Pp
47287f5f0ecSDag-Erling SmørgravFinally,
47387f5f0ecSDag-Erling Smørgravthe
47487f5f0ecSDag-Erling Smørgrav.Fa CMP
4759d44cd42SBenno Riceargument is the name of a function used to compare tree nodes
476480565d5SRuslan Ermilovwith each other.
477480565d5SRuslan ErmilovThe function takes two arguments of type
478480565d5SRuslan Ermilov.Vt "struct TYPE *" .
47987f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a
480480565d5SRuslan Ermilovvalue smaller than zero.
481480565d5SRuslan ErmilovIf they are equal, the function returns zero.
482480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero.
483480565d5SRuslan ErmilovThe compare
48487f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements.
48587f5f0ecSDag-Erling Smørgrav.Pp
48687f5f0ecSDag-Erling SmørgravThe
48787f5f0ecSDag-Erling Smørgrav.Fn RB_INIT
48887f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by
48987f5f0ecSDag-Erling Smørgrav.Fa head .
49087f5f0ecSDag-Erling Smørgrav.Pp
4913b96c71fSMike PritchardThe red-black tree can also be initialized statically by using the
49287f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER
49387f5f0ecSDag-Erling Smørgravmacro like this:
494480565d5SRuslan Ermilov.Bd -ragged -offset indent
495480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
496480565d5SRuslan Ermilov.Va head
497480565d5SRuslan Ermilov=
498480565d5SRuslan Ermilov.Fn RB_INITIALIZER &head ;
49987f5f0ecSDag-Erling Smørgrav.Ed
50087f5f0ecSDag-Erling Smørgrav.Pp
50187f5f0ecSDag-Erling SmørgravThe
50287f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT
50387f5f0ecSDag-Erling Smørgravmacro inserts the new element
50487f5f0ecSDag-Erling Smørgrav.Fa elm
50587f5f0ecSDag-Erling Smørgravinto the tree.
50687f5f0ecSDag-Erling Smørgrav.Pp
50787f5f0ecSDag-Erling SmørgravThe
50887f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE
50987f5f0ecSDag-Erling Smørgravmacro removes the element
51087f5f0ecSDag-Erling Smørgrav.Fa elm
51187f5f0ecSDag-Erling Smørgravfrom the tree pointed by
51287f5f0ecSDag-Erling Smørgrav.Fa head .
51387f5f0ecSDag-Erling Smørgrav.Pp
51487f5f0ecSDag-Erling SmørgravThe
51587f5f0ecSDag-Erling Smørgrav.Fn RB_FIND
51606115e08SJason Evansand
51706115e08SJason Evans.Fn RB_NFIND
51806115e08SJason Evansmacros can be used to find a particular element in the tree.
51987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
52087f5f0ecSDag-Erling Smørgravstruct TYPE find, *res;
52187f5f0ecSDag-Erling Smørgravfind.key = 30;
52287f5f0ecSDag-Erling Smørgravres = RB_FIND(NAME, head, &find);
52387f5f0ecSDag-Erling Smørgrav.Ed
52487f5f0ecSDag-Erling Smørgrav.Pp
52587f5f0ecSDag-Erling SmørgravThe
52687f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT ,
52787f5f0ecSDag-Erling Smørgrav.Fn RB_MIN ,
52887f5f0ecSDag-Erling Smørgrav.Fn RB_MAX ,
5298e4fd0a1SJason Evans.Fn RB_NEXT ,
53087f5f0ecSDag-Erling Smørgravand
5318e4fd0a1SJason Evans.Fn RB_PREV
53287f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree:
533480565d5SRuslan Ermilov.Pp
534480565d5SRuslan Ermilov.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))"
53587f5f0ecSDag-Erling Smørgrav.Pp
53687f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the
53787f5f0ecSDag-Erling Smørgrav.Fn RB_FOREACH
5388e4fd0a1SJason Evansor
5398e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE
54087f5f0ecSDag-Erling Smørgravmacro:
541480565d5SRuslan Ermilov.Bd -ragged -offset indent
542480565d5SRuslan Ermilov.Fn RB_FOREACH np NAME head
54387f5f0ecSDag-Erling Smørgrav.Ed
54487f5f0ecSDag-Erling Smørgrav.Pp
5459dbae282SGleb SmirnoffThe macros
5469dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE
5479dbae282SGleb Smirnoffand
5489dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE
5499dbae282SGleb Smirnofftraverse the tree referenced by head
5509dbae282SGleb Smirnoffin a forward or reverse direction respectively,
5519dbae282SGleb Smirnoffassigning each element in turn to np.
5529dbae282SGleb SmirnoffHowever, unlike their unsafe counterparts,
5539dbae282SGleb Smirnoffthey permit both the removal of np
5549dbae282SGleb Smirnoffas well as freeing it from within the loop safely
5559dbae282SGleb Smirnoffwithout interfering with the traversal.
5569dbae282SGleb Smirnoff.Pp
557bff27689SBruce M SimpsonBoth
558bff27689SBruce M Simpson.Fn RB_FOREACH_FROM
559bff27689SBruce M Simpsonand
560bff27689SBruce M Simpson.Fn RB_FOREACH_REVERSE_FROM
561bff27689SBruce M Simpsonmay be used to continue an interrupted traversal
562bff27689SBruce M Simpsonin a forward or reverse direction respectively.
563639bf7bdSBruce M SimpsonThe head pointer is not required.
564639bf7bdSBruce M SimpsonThe pointer to the node from where to resume the traversal
565639bf7bdSBruce M Simpsonshould be passed as their last argument,
566bff27689SBruce M Simpsonand will be overwritten to provide safe traversal.
567bff27689SBruce M Simpson.Pp
56887f5f0ecSDag-Erling SmørgravThe
56987f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY
570309e4b9bSDag-Erling Smørgravmacro should be used to check whether a red-black tree is empty.
57122823764SEdward Tomasz Napierala.Pp
57222823764SEdward Tomasz NapieralaThe
57322823764SEdward Tomasz Napierala.Fn RB_REINSERT
57422823764SEdward Tomasz Napieralamacro updates the position of the element
57522823764SEdward Tomasz Napierala.Fa elm
57622823764SEdward Tomasz Napieralain the tree.
57722823764SEdward Tomasz NapieralaThis must be called if a member of a
57822823764SEdward Tomasz Napierala.Nm tree
57922823764SEdward Tomasz Napieralais modified in a way that affects comparison, such as by modifying
58022823764SEdward Tomasz Napieralaa node's key.
58122823764SEdward Tomasz NapieralaThis is a lower overhead alternative to removing the element
58222823764SEdward Tomasz Napieralaand reinserting it again.
583ac0879c3SEdward Tomasz Napierala.Sh EXAMPLES
584ac0879c3SEdward Tomasz NapieralaThe following example demonstrates how to declare a red-black tree
585ac0879c3SEdward Tomasz Napieralaholding integers.
586ac0879c3SEdward Tomasz NapieralaValues are inserted into it and the contents of the tree are printed
587ac0879c3SEdward Tomasz Napieralain order.
588ac0879c3SEdward Tomasz NapieralaLastly, the internal structure of the tree is printed.
589ac0879c3SEdward Tomasz Napierala.Bd -literal -offset 3n
590ac0879c3SEdward Tomasz Napierala#include <sys/tree.h>
591ac0879c3SEdward Tomasz Napierala#include <err.h>
592ac0879c3SEdward Tomasz Napierala#include <stdio.h>
593ac0879c3SEdward Tomasz Napierala#include <stdlib.h>
594ac0879c3SEdward Tomasz Napierala
595ac0879c3SEdward Tomasz Napieralastruct node {
596ac0879c3SEdward Tomasz Napierala	RB_ENTRY(node) entry;
597ac0879c3SEdward Tomasz Napierala	int i;
598ac0879c3SEdward Tomasz Napierala};
599ac0879c3SEdward Tomasz Napierala
600ac0879c3SEdward Tomasz Napieralaint
601ac0879c3SEdward Tomasz Napieralaintcmp(struct node *e1, struct node *e2)
602ac0879c3SEdward Tomasz Napierala{
603ac0879c3SEdward Tomasz Napierala	return (e1->i < e2->i ? -1 : e1->i > e2->i);
604ac0879c3SEdward Tomasz Napierala}
605ac0879c3SEdward Tomasz Napierala
606ac0879c3SEdward Tomasz NapieralaRB_HEAD(inttree, node) head = RB_INITIALIZER(&head);
607ac0879c3SEdward Tomasz NapieralaRB_GENERATE(inttree, node, entry, intcmp)
608ac0879c3SEdward Tomasz Napierala
609ac0879c3SEdward Tomasz Napieralaint testdata[] = {
610ac0879c3SEdward Tomasz Napierala	20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18,
611ac0879c3SEdward Tomasz Napierala	7, 11, 14
612ac0879c3SEdward Tomasz Napierala};
613ac0879c3SEdward Tomasz Napierala
614ac0879c3SEdward Tomasz Napieralavoid
615ac0879c3SEdward Tomasz Napieralaprint_tree(struct node *n)
616ac0879c3SEdward Tomasz Napierala{
617ac0879c3SEdward Tomasz Napierala	struct node *left, *right;
618ac0879c3SEdward Tomasz Napierala
619ac0879c3SEdward Tomasz Napierala	if (n == NULL) {
620ac0879c3SEdward Tomasz Napierala		printf("nil");
621ac0879c3SEdward Tomasz Napierala		return;
622ac0879c3SEdward Tomasz Napierala	}
623ac0879c3SEdward Tomasz Napierala	left = RB_LEFT(n, entry);
624ac0879c3SEdward Tomasz Napierala	right = RB_RIGHT(n, entry);
625ac0879c3SEdward Tomasz Napierala	if (left == NULL && right == NULL)
626ac0879c3SEdward Tomasz Napierala		printf("%d", n->i);
627ac0879c3SEdward Tomasz Napierala	else {
628ac0879c3SEdward Tomasz Napierala		printf("%d(", n->i);
629ac0879c3SEdward Tomasz Napierala		print_tree(left);
630ac0879c3SEdward Tomasz Napierala		printf(",");
631ac0879c3SEdward Tomasz Napierala		print_tree(right);
632ac0879c3SEdward Tomasz Napierala		printf(")");
633ac0879c3SEdward Tomasz Napierala	}
634ac0879c3SEdward Tomasz Napierala}
635ac0879c3SEdward Tomasz Napierala
636ac0879c3SEdward Tomasz Napieralaint
637ac0879c3SEdward Tomasz Napieralamain(void)
638ac0879c3SEdward Tomasz Napierala{
639ac0879c3SEdward Tomasz Napierala	int i;
640ac0879c3SEdward Tomasz Napierala	struct node *n;
641ac0879c3SEdward Tomasz Napierala
642ac0879c3SEdward Tomasz Napierala	for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) {
643ac0879c3SEdward Tomasz Napierala		if ((n = malloc(sizeof(struct node))) == NULL)
644ac0879c3SEdward Tomasz Napierala			err(1, NULL);
645ac0879c3SEdward Tomasz Napierala		n->i = testdata[i];
646ac0879c3SEdward Tomasz Napierala		RB_INSERT(inttree, &head, n);
647ac0879c3SEdward Tomasz Napierala	}
648ac0879c3SEdward Tomasz Napierala
649ac0879c3SEdward Tomasz Napierala	RB_FOREACH(n, inttree, &head) {
650ac0879c3SEdward Tomasz Napierala		printf("%d\en", n->i);
651ac0879c3SEdward Tomasz Napierala	}
652ac0879c3SEdward Tomasz Napierala	print_tree(RB_ROOT(&head));
653ac0879c3SEdward Tomasz Napierala	printf("\en");
654ac0879c3SEdward Tomasz Napierala	return (0);
655ac0879c3SEdward Tomasz Napierala}
656ac0879c3SEdward Tomasz Napierala.Ed
65787f5f0ecSDag-Erling Smørgrav.Sh NOTES
65887f5f0ecSDag-Erling SmørgravTrying to free a tree in the following way is a common error:
65987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
66087f5f0ecSDag-Erling SmørgravSPLAY_FOREACH(var, NAME, head) {
66187f5f0ecSDag-Erling Smørgrav	SPLAY_REMOVE(NAME, head, var);
66287f5f0ecSDag-Erling Smørgrav	free(var);
66387f5f0ecSDag-Erling Smørgrav}
66487f5f0ecSDag-Erling Smørgravfree(head);
66587f5f0ecSDag-Erling Smørgrav.Ed
66687f5f0ecSDag-Erling Smørgrav.Pp
66787f5f0ecSDag-Erling SmørgravSince
66887f5f0ecSDag-Erling Smørgrav.Va var
669480565d5SRuslan Ermilovis freed, the
67087f5f0ecSDag-Erling Smørgrav.Fn FOREACH
67187f5f0ecSDag-Erling Smørgravmacro refers to a pointer that may have been reallocated already.
67287f5f0ecSDag-Erling SmørgravProper code needs a second variable.
67387f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
67487f5f0ecSDag-Erling Smørgravfor (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) {
67587f5f0ecSDag-Erling Smørgrav	nxt = SPLAY_NEXT(NAME, head, var);
67687f5f0ecSDag-Erling Smørgrav	SPLAY_REMOVE(NAME, head, var);
67787f5f0ecSDag-Erling Smørgrav	free(var);
67887f5f0ecSDag-Erling Smørgrav}
67987f5f0ecSDag-Erling Smørgrav.Ed
68087f5f0ecSDag-Erling Smørgrav.Pp
68187f5f0ecSDag-Erling SmørgravBoth
68287f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT
68387f5f0ecSDag-Erling Smørgravand
68487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT
68587f5f0ecSDag-Erling Smørgravreturn
686480565d5SRuslan Ermilov.Dv NULL
68787f5f0ecSDag-Erling Smørgravif the element was inserted in the tree successfully, otherwise they
68887f5f0ecSDag-Erling Smørgravreturn a pointer to the element with the colliding key.
68987f5f0ecSDag-Erling Smørgrav.Pp
69087f5f0ecSDag-Erling SmørgravAccordingly,
69187f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE
69287f5f0ecSDag-Erling Smørgravand
69387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE
69487f5f0ecSDag-Erling Smørgravreturn the pointer to the removed element otherwise they return
695480565d5SRuslan Ermilov.Dv NULL
69687f5f0ecSDag-Erling Smørgravto indicate an error.
697b9ec8f3bSSimon L. B. Nielsen.Sh SEE ALSO
698fad4b12bSEdward Tomasz Napierala.Xr arb 3 ,
699b9ec8f3bSSimon L. B. Nielsen.Xr queue 3
700*757a04bfSSergio Carlavilla Delgado.Sh HISTORY
701*757a04bfSSergio Carlavilla DelgadoThe tree macros first appeared in
702*757a04bfSSergio Carlavilla Delgado.Fx 4.6 .
70387f5f0ecSDag-Erling Smørgrav.Sh AUTHORS
704480565d5SRuslan ErmilovThe author of the tree macros is
705480565d5SRuslan Ermilov.An Niels Provos .
706