xref: /freebsd/share/man/man3/tree.3 (revision 480565d5e4451c465fa887b6d0fad4c60c50a410)
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.\"
3387f5f0ecSDag-Erling Smørgrav.Dd February 24, 2002
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 ,
5587f5f0ecSDag-Erling Smørgrav.Nm RB_GENERATE ,
5687f5f0ecSDag-Erling Smørgrav.Nm RB_ENTRY ,
5787f5f0ecSDag-Erling Smørgrav.Nm RB_HEAD ,
5887f5f0ecSDag-Erling Smørgrav.Nm RB_INITIALIZER ,
5987f5f0ecSDag-Erling Smørgrav.Nm RB_ROOT ,
6087f5f0ecSDag-Erling Smørgrav.Nm RB_EMPTY ,
6187f5f0ecSDag-Erling Smørgrav.Nm RB_NEXT ,
6287f5f0ecSDag-Erling Smørgrav.Nm RB_MIN ,
6387f5f0ecSDag-Erling Smørgrav.Nm RB_MAX ,
6487f5f0ecSDag-Erling Smørgrav.Nm RB_FIND ,
6587f5f0ecSDag-Erling Smørgrav.Nm RB_LEFT ,
6687f5f0ecSDag-Erling Smørgrav.Nm RB_RIGHT ,
6787f5f0ecSDag-Erling Smørgrav.Nm RB_PARENT ,
6887f5f0ecSDag-Erling Smørgrav.Nm RB_FOREACH ,
6987f5f0ecSDag-Erling Smørgrav.Nm RB_INIT ,
7087f5f0ecSDag-Erling Smørgrav.Nm RB_INSERT ,
7187f5f0ecSDag-Erling Smørgrav.Nm RB_REMOVE
7287f5f0ecSDag-Erling Smørgrav.Nd "implementations of splay and red-black trees"
7387f5f0ecSDag-Erling Smørgrav.Sh SYNOPSIS
74480565d5SRuslan Ermilov.In sys/tree.h
75480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP
76480565d5SRuslan Ermilov.Fn SPLAY_GENERATE NAME TYPE FIELD CMP
77480565d5SRuslan Ermilov.Fn SPLAY_ENTRY TYPE
78480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
7987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
8087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head"
8187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT "SPLAY_HEAD *head"
82480565d5SRuslan Ermilov.Ft bool
8387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY "SPLAY_HEAD *head"
8487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
85480565d5SRuslan Ermilov.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
8687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
87480565d5SRuslan Ermilov.Fn SPLAY_MIN NAME "SPLAY_HEAD *head"
8887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
89480565d5SRuslan Ermilov.Fn SPLAY_MAX NAME "SPLAY_HEAD *head"
9087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
91480565d5SRuslan Ermilov.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm"
9287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
9387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME"
9487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
9587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME"
96480565d5SRuslan Ermilov.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head"
9787f5f0ecSDag-Erling Smørgrav.Ft void
9887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT "SPLAY_HEAD *head"
9987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
100480565d5SRuslan Ermilov.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
10187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
102480565d5SRuslan Ermilov.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm"
103480565d5SRuslan Ermilov.Fn RB_PROTOTYPE NAME TYPE FIELD CMP
104480565d5SRuslan Ermilov.Fn RB_GENERATE NAME TYPE FIELD CMP
105480565d5SRuslan Ermilov.Fn RB_ENTRY TYPE
106480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
10787f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER "RB_HEAD *head"
10887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
10987f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT "RB_HEAD *head"
11087f5f0ecSDag-Erling Smørgrav.Ft "bool"
11187f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY "RB_HEAD *head"
11287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
113480565d5SRuslan Ermilov.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm"
11487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
115480565d5SRuslan Ermilov.Fn RB_MIN NAME "RB_HEAD *head"
11687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
117480565d5SRuslan Ermilov.Fn RB_MAX NAME "RB_HEAD *head"
11887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
119480565d5SRuslan Ermilov.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm"
12087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
12187f5f0ecSDag-Erling Smørgrav.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME"
12287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
12387f5f0ecSDag-Erling Smørgrav.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME"
12487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
12587f5f0ecSDag-Erling Smørgrav.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
126480565d5SRuslan Ermilov.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head"
12787f5f0ecSDag-Erling Smørgrav.Ft void
12887f5f0ecSDag-Erling Smørgrav.Fn RB_INIT "RB_HEAD *head"
12987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
130480565d5SRuslan Ermilov.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm"
13187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
132480565d5SRuslan Ermilov.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm"
13387f5f0ecSDag-Erling Smørgrav.Sh DESCRIPTION
134480565d5SRuslan ErmilovThese macros define data structures for different types of trees:
13587f5f0ecSDag-Erling Smørgravsplay trees and red-black trees.
13687f5f0ecSDag-Erling Smørgrav.Pp
13787f5f0ecSDag-Erling SmørgravIn the macro definitions,
13887f5f0ecSDag-Erling Smørgrav.Fa TYPE
13987f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must contain a field of type
140480565d5SRuslan Ermilov.Vt SPLAY_ENTRY ,
14187f5f0ecSDag-Erling Smørgravor
142480565d5SRuslan Ermilov.Vt RB_ENTRY ,
14387f5f0ecSDag-Erling Smørgravnamed
14487f5f0ecSDag-Erling Smørgrav.Fa ENTRYNAME .
14587f5f0ecSDag-Erling SmørgravThe argument
14687f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
14787f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must be declared
14887f5f0ecSDag-Erling Smørgravusing the macros
14987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD ,
15087f5f0ecSDag-Erling Smørgravor
15187f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD .
15287f5f0ecSDag-Erling SmørgravThe argument
15387f5f0ecSDag-Erling Smørgrav.Fa NAME
15487f5f0ecSDag-Erling Smørgravhas to be a unique name prefix for every tree that is defined.
15587f5f0ecSDag-Erling Smørgrav.Pp
15687f5f0ecSDag-Erling SmørgravThe function prototypes are declared with either
157480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE ,
15887f5f0ecSDag-Erling Smørgravor
159480565d5SRuslan Ermilov.Fn RB_PROTOTYPE .
16087f5f0ecSDag-Erling SmørgravThe function bodies are generated with either
161480565d5SRuslan Ermilov.Fn SPLAY_GENERATE ,
16287f5f0ecSDag-Erling Smørgravor
163480565d5SRuslan Ermilov.Fn RB_GENERATE .
16487f5f0ecSDag-Erling SmørgravSee the examples below for further explanation of how these macros are used.
16587f5f0ecSDag-Erling Smørgrav.Sh SPLAY TREES
166480565d5SRuslan ErmilovA splay tree is a self-organizing data structure.
167480565d5SRuslan ErmilovEvery operation on the tree causes a splay to happen.
168480565d5SRuslan ErmilovThe splay moves the requested
16987f5f0ecSDag-Erling Smørgravnode to the root of the tree and partly rebalances it.
17087f5f0ecSDag-Erling Smørgrav.Pp
17187f5f0ecSDag-Erling SmørgravThis has the benefit that request locality causes faster lookups as
172480565d5SRuslan Ermilovthe requested nodes move to the top of the tree.
173480565d5SRuslan ErmilovOn the other hand, every lookup causes memory writes.
17487f5f0ecSDag-Erling Smørgrav.Pp
175480565d5SRuslan ErmilovThe Balance Theorem bounds the total access time for
176480565d5SRuslan Ermilov.Ar m
177480565d5SRuslan Ermilovoperations and
178480565d5SRuslan Ermilov.Ar n
179480565d5SRuslan Ermilovinserts on an initially empty tree as
180480565d5SRuslan Ermilov.Fn O "\*[lp]m + n\*[rp]lg n" .
181480565d5SRuslan ErmilovThe
182480565d5SRuslan Ermilovamortized cost for a sequence of
183480565d5SRuslan Ermilov.Ar m
184480565d5SRuslan Ermilovaccesses to a splay tree is
185480565d5SRuslan Ermilov.Fn O "lg n" .
18687f5f0ecSDag-Erling Smørgrav.Pp
18787f5f0ecSDag-Erling SmørgravA splay tree is headed by a structure defined by the
18887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD
18987f5f0ecSDag-Erling Smørgravmacro.
19087f5f0ecSDag-Erling SmørgravA
19187f5f0ecSDag-Erling Smørgravstructure is declared as follows:
192480565d5SRuslan Ermilov.Bd -ragged -offset indent
193480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
194480565d5SRuslan Ermilov.Va head ;
19587f5f0ecSDag-Erling Smørgrav.Ed
19687f5f0ecSDag-Erling Smørgrav.Pp
19787f5f0ecSDag-Erling Smørgravwhere
19887f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
19987f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct
20087f5f0ecSDag-Erling Smørgrav.Fa TYPE
20187f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree.
20287f5f0ecSDag-Erling Smørgrav.Pp
20387f5f0ecSDag-Erling SmørgravThe
20487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY
20587f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree.
20687f5f0ecSDag-Erling Smørgrav.Pp
20787f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure,
20887f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the
20987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE
21087f5f0ecSDag-Erling Smørgravmacro,
21187f5f0ecSDag-Erling Smørgravwhere
21287f5f0ecSDag-Erling Smørgrav.Fa NAME
21387f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree.
21487f5f0ecSDag-Erling SmørgravThe
21587f5f0ecSDag-Erling Smørgrav.Fa TYPE
21687f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed
21787f5f0ecSDag-Erling Smørgravby the tree.
21887f5f0ecSDag-Erling SmørgravThe
21987f5f0ecSDag-Erling Smørgrav.Fa FIELD
22087f5f0ecSDag-Erling Smørgravargument is the name of the element defined by
22187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY .
22287f5f0ecSDag-Erling Smørgrav.Pp
22387f5f0ecSDag-Erling SmørgravThe function bodies are generated with the
22487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_GENERATE
225480565d5SRuslan Ermilovmacro.
226480565d5SRuslan ErmilovIt takes the same arguments as the
22787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE
22887f5f0ecSDag-Erling Smørgravmacro, but should be used only once.
22987f5f0ecSDag-Erling Smørgrav.Pp
23087f5f0ecSDag-Erling SmørgravFinally,
23187f5f0ecSDag-Erling Smørgravthe
23287f5f0ecSDag-Erling Smørgrav.Fa CMP
233480565d5SRuslan Ermilovargument is the name of a function used to compare tree nodes
234480565d5SRuslan Ermilovwith each other.
235480565d5SRuslan ErmilovThe function takes two arguments of type
236480565d5SRuslan Ermilov.Vt "struct TYPE *" .
23787f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a
238480565d5SRuslan Ermilovvalue smaller than zero.
239480565d5SRuslan ErmilovIf they are equal, the function returns zero.
240480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero.
241480565d5SRuslan ErmilovThe compare
24287f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements.
24387f5f0ecSDag-Erling Smørgrav.Pp
24487f5f0ecSDag-Erling SmørgravThe
24587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT
24687f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by
24787f5f0ecSDag-Erling Smørgrav.Fa head .
24887f5f0ecSDag-Erling Smørgrav.Pp
24987f5f0ecSDag-Erling SmørgravThe splay tree can also be initialized statically by using the
25087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER
25187f5f0ecSDag-Erling Smørgravmacro like this:
252480565d5SRuslan Ermilov.Bd -ragged -offset indent
253480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
254480565d5SRuslan Ermilov.Va head
255480565d5SRuslan Ermilov=
256480565d5SRuslan Ermilov.Fn SPLAY_INITIALIZER &head ;
25787f5f0ecSDag-Erling Smørgrav.Ed
25887f5f0ecSDag-Erling Smørgrav.Pp
25987f5f0ecSDag-Erling SmørgravThe
26087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT
26187f5f0ecSDag-Erling Smørgravmacro inserts the new element
26287f5f0ecSDag-Erling Smørgrav.Fa elm
26387f5f0ecSDag-Erling Smørgravinto the tree.
26487f5f0ecSDag-Erling Smørgrav.Pp
26587f5f0ecSDag-Erling SmørgravThe
26687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE
26787f5f0ecSDag-Erling Smørgravmacro removes the element
26887f5f0ecSDag-Erling Smørgrav.Fa elm
26987f5f0ecSDag-Erling Smørgravfrom the tree pointed by
27087f5f0ecSDag-Erling Smørgrav.Fa head .
27187f5f0ecSDag-Erling Smørgrav.Pp
27287f5f0ecSDag-Erling SmørgravThe
27387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FIND
27487f5f0ecSDag-Erling Smørgravmacro can be used to find a particular element in the tree.
27587f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
27687f5f0ecSDag-Erling Smørgravstruct TYPE find, *res;
27787f5f0ecSDag-Erling Smørgravfind.key = 30;
27887f5f0ecSDag-Erling Smørgravres = SPLAY_FIND(NAME, head, &find);
27987f5f0ecSDag-Erling Smørgrav.Ed
28087f5f0ecSDag-Erling Smørgrav.Pp
28187f5f0ecSDag-Erling SmørgravThe
28287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT ,
28387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MIN ,
28487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MAX ,
28587f5f0ecSDag-Erling Smørgravand
28687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_NEXT
28787f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree:
28887f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
28987f5f0ecSDag-Erling Smørgravfor (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np))
29087f5f0ecSDag-Erling Smørgrav.Ed
29187f5f0ecSDag-Erling Smørgrav.Pp
29287f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the
29387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FOREACH
29487f5f0ecSDag-Erling Smørgravmacro:
295480565d5SRuslan Ermilov.Bd -ragged -offset indent
296480565d5SRuslan Ermilov.Fn SPLAY_FOREACH np NAME head
29787f5f0ecSDag-Erling Smørgrav.Ed
29887f5f0ecSDag-Erling Smørgrav.Pp
29987f5f0ecSDag-Erling SmørgravThe
30087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY
30187f5f0ecSDag-Erling Smørgravmacro should be used to check whether a splay tree is empty.
30287f5f0ecSDag-Erling Smørgrav.Sh RED-BLACK TREES
30387f5f0ecSDag-Erling SmørgravA red-black tree is a binary search tree with the node color as an
304480565d5SRuslan Ermilovextra attribute.
305480565d5SRuslan ErmilovIt fulfills a set of conditions:
306480565d5SRuslan Ermilov.Bl -enum -offset indent
30787f5f0ecSDag-Erling Smørgrav.It
308480565d5SRuslan ErmilovEvery search path from the root to a leaf consists of the same number of
309480565d5SRuslan Ermilovblack nodes.
31087f5f0ecSDag-Erling Smørgrav.It
311480565d5SRuslan ErmilovEach red node (except for the root) has a black parent.
31287f5f0ecSDag-Erling Smørgrav.It
313480565d5SRuslan ErmilovEach leaf node is black.
31487f5f0ecSDag-Erling Smørgrav.El
31587f5f0ecSDag-Erling Smørgrav.Pp
316480565d5SRuslan ErmilovEvery operation on a red-black tree is bounded as
317480565d5SRuslan Ermilov.Fn O "lg n" .
318480565d5SRuslan ErmilovThe maximum height of a red-black tree is
319480565d5SRuslan Ermilov.Fn 2lg "n + 1" .
32087f5f0ecSDag-Erling Smørgrav.Pp
32187f5f0ecSDag-Erling SmørgravA red-black tree is headed by a structure defined by the
32287f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD
32387f5f0ecSDag-Erling Smørgravmacro.
32487f5f0ecSDag-Erling SmørgravA
32587f5f0ecSDag-Erling Smørgravstructure is declared as follows:
326480565d5SRuslan Ermilov.Bd -ragged -offset indent
327480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
328480565d5SRuslan Ermilov.Va head ;
32987f5f0ecSDag-Erling Smørgrav.Ed
33087f5f0ecSDag-Erling Smørgrav.Pp
33187f5f0ecSDag-Erling Smørgravwhere
33287f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
33387f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct
33487f5f0ecSDag-Erling Smørgrav.Fa TYPE
33587f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree.
33687f5f0ecSDag-Erling Smørgrav.Pp
33787f5f0ecSDag-Erling SmørgravThe
33887f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY
33987f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree.
34087f5f0ecSDag-Erling Smørgrav.Pp
34187f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure,
34287f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the
34387f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE
34487f5f0ecSDag-Erling Smørgravmacro,
34587f5f0ecSDag-Erling Smørgravwhere
34687f5f0ecSDag-Erling Smørgrav.Fa NAME
34787f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree.
34887f5f0ecSDag-Erling SmørgravThe
34987f5f0ecSDag-Erling Smørgrav.Fa TYPE
35087f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed
35187f5f0ecSDag-Erling Smørgravby the tree.
35287f5f0ecSDag-Erling SmørgravThe
35387f5f0ecSDag-Erling Smørgrav.Fa FIELD
35487f5f0ecSDag-Erling Smørgravargument is the name of the element defined by
35587f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY .
35687f5f0ecSDag-Erling Smørgrav.Pp
35787f5f0ecSDag-Erling SmørgravThe function bodies are generated with the
35887f5f0ecSDag-Erling Smørgrav.Fn RB_GENERATE
359480565d5SRuslan Ermilovmacro.
360480565d5SRuslan ErmilovIt takes the same arguments as the
36187f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE
36287f5f0ecSDag-Erling Smørgravmacro, but should be used only once.
36387f5f0ecSDag-Erling Smørgrav.Pp
36487f5f0ecSDag-Erling SmørgravFinally,
36587f5f0ecSDag-Erling Smørgravthe
36687f5f0ecSDag-Erling Smørgrav.Fa CMP
36787f5f0ecSDag-Erling Smørgravargument is the name of a function used to compare tree noded
368480565d5SRuslan Ermilovwith each other.
369480565d5SRuslan ErmilovThe function takes two arguments of type
370480565d5SRuslan Ermilov.Vt "struct TYPE *" .
37187f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a
372480565d5SRuslan Ermilovvalue smaller than zero.
373480565d5SRuslan ErmilovIf they are equal, the function returns zero.
374480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero.
375480565d5SRuslan ErmilovThe compare
37687f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements.
37787f5f0ecSDag-Erling Smørgrav.Pp
37887f5f0ecSDag-Erling SmørgravThe
37987f5f0ecSDag-Erling Smørgrav.Fn RB_INIT
38087f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by
38187f5f0ecSDag-Erling Smørgrav.Fa head .
38287f5f0ecSDag-Erling Smørgrav.Pp
38387f5f0ecSDag-Erling SmørgravThe redblack tree can also be initialized statically by using the
38487f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER
38587f5f0ecSDag-Erling Smørgravmacro like this:
386480565d5SRuslan Ermilov.Bd -ragged -offset indent
387480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
388480565d5SRuslan Ermilov.Va head
389480565d5SRuslan Ermilov=
390480565d5SRuslan Ermilov.Fn RB_INITIALIZER &head ;
39187f5f0ecSDag-Erling Smørgrav.Ed
39287f5f0ecSDag-Erling Smørgrav.Pp
39387f5f0ecSDag-Erling SmørgravThe
39487f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT
39587f5f0ecSDag-Erling Smørgravmacro inserts the new element
39687f5f0ecSDag-Erling Smørgrav.Fa elm
39787f5f0ecSDag-Erling Smørgravinto the tree.
39887f5f0ecSDag-Erling Smørgrav.Pp
39987f5f0ecSDag-Erling SmørgravThe
40087f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE
40187f5f0ecSDag-Erling Smørgravmacro removes the element
40287f5f0ecSDag-Erling Smørgrav.Fa elm
40387f5f0ecSDag-Erling Smørgravfrom the tree pointed by
40487f5f0ecSDag-Erling Smørgrav.Fa head .
40587f5f0ecSDag-Erling Smørgrav.Pp
40687f5f0ecSDag-Erling SmørgravThe
40787f5f0ecSDag-Erling Smørgrav.Fn RB_FIND
40887f5f0ecSDag-Erling Smørgravmacro can be used to find a particular element in the tree.
40987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
41087f5f0ecSDag-Erling Smørgravstruct TYPE find, *res;
41187f5f0ecSDag-Erling Smørgravfind.key = 30;
41287f5f0ecSDag-Erling Smørgravres = RB_FIND(NAME, head, &find);
41387f5f0ecSDag-Erling Smørgrav.Ed
41487f5f0ecSDag-Erling Smørgrav.Pp
41587f5f0ecSDag-Erling SmørgravThe
41687f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT ,
41787f5f0ecSDag-Erling Smørgrav.Fn RB_MIN ,
41887f5f0ecSDag-Erling Smørgrav.Fn RB_MAX ,
41987f5f0ecSDag-Erling Smørgravand
42087f5f0ecSDag-Erling Smørgrav.Fn RB_NEXT
42187f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree:
422480565d5SRuslan Ermilov.Pp
423480565d5SRuslan Ermilov.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))"
42487f5f0ecSDag-Erling Smørgrav.Pp
42587f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the
42687f5f0ecSDag-Erling Smørgrav.Fn RB_FOREACH
42787f5f0ecSDag-Erling Smørgravmacro:
428480565d5SRuslan Ermilov.Bd -ragged -offset indent
429480565d5SRuslan Ermilov.Fn RB_FOREACH np NAME head
43087f5f0ecSDag-Erling Smørgrav.Ed
43187f5f0ecSDag-Erling Smørgrav.Pp
43287f5f0ecSDag-Erling SmørgravThe
43387f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY
43487f5f0ecSDag-Erling Smørgravmacro should be used to check whether a splay tree is empty.
43587f5f0ecSDag-Erling Smørgrav.Sh NOTES
43687f5f0ecSDag-Erling SmørgravTrying to free a tree in the following way is a common error:
43787f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
43887f5f0ecSDag-Erling SmørgravSPLAY_FOREACH(var, NAME, head) {
43987f5f0ecSDag-Erling Smørgrav	SPLAY_REMOVE(NAME, head, var);
44087f5f0ecSDag-Erling Smørgrav	free(var);
44187f5f0ecSDag-Erling Smørgrav}
44287f5f0ecSDag-Erling Smørgravfree(head);
44387f5f0ecSDag-Erling Smørgrav.Ed
44487f5f0ecSDag-Erling Smørgrav.Pp
44587f5f0ecSDag-Erling SmørgravSince
44687f5f0ecSDag-Erling Smørgrav.Va var
447480565d5SRuslan Ermilovis freed, the
44887f5f0ecSDag-Erling Smørgrav.Fn FOREACH
44987f5f0ecSDag-Erling Smørgravmacro refers to a pointer that may have been reallocated already.
45087f5f0ecSDag-Erling SmørgravProper code needs a second variable.
45187f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
45287f5f0ecSDag-Erling Smørgravfor (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) {
45387f5f0ecSDag-Erling Smørgrav	nxt = SPLAY_NEXT(NAME, head, var);
45487f5f0ecSDag-Erling Smørgrav	SPLAY_REMOVE(NAME, head, var);
45587f5f0ecSDag-Erling Smørgrav	free(var);
45687f5f0ecSDag-Erling Smørgrav}
45787f5f0ecSDag-Erling Smørgrav.Ed
45887f5f0ecSDag-Erling Smørgrav.Pp
45987f5f0ecSDag-Erling SmørgravBoth
46087f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT
46187f5f0ecSDag-Erling Smørgravand
46287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT
46387f5f0ecSDag-Erling Smørgravreturn
464480565d5SRuslan Ermilov.Dv NULL
46587f5f0ecSDag-Erling Smørgravif the element was inserted in the tree successfully, otherwise they
46687f5f0ecSDag-Erling Smørgravreturn a pointer to the element with the colliding key.
46787f5f0ecSDag-Erling Smørgrav.Pp
46887f5f0ecSDag-Erling SmørgravAccordingly,
46987f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE
47087f5f0ecSDag-Erling Smørgravand
47187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE
47287f5f0ecSDag-Erling Smørgravreturn the pointer to the removed element otherwise they return
473480565d5SRuslan Ermilov.Dv NULL
47487f5f0ecSDag-Erling Smørgravto indicate an error.
47587f5f0ecSDag-Erling Smørgrav.Sh AUTHORS
476480565d5SRuslan ErmilovThe author of the tree macros is
477480565d5SRuslan Ermilov.An Niels Provos .
478