xref: /freebsd/share/man/man3/tree.3 (revision 08349b18ea26d1e191333f9b3550cd95b09cfe34)
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.\"
3358f5de0dSMateusz Piotrowski.Dd July 27, 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 ,
101a8380d27SDoug Moore.Nm RB_REINSERT ,
102a8380d27SDoug Moore.Nm RB_AUGMENT
10335557a0dSDoug Moore.Nm RB_UPDATE_AUGMENT
104e605dcc9SDoug Moore.Nd "implementations of splay and rank-balanced (wavl) trees"
10587f5f0ecSDag-Erling Smørgrav.Sh SYNOPSIS
106480565d5SRuslan Ermilov.In sys/tree.h
107480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP
108480565d5SRuslan Ermilov.Fn SPLAY_GENERATE NAME TYPE FIELD CMP
109480565d5SRuslan Ermilov.Fn SPLAY_ENTRY TYPE
110480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
11187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
11287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head"
11387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT "SPLAY_HEAD *head"
114480565d5SRuslan Ermilov.Ft bool
11587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY "SPLAY_HEAD *head"
11687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
117480565d5SRuslan Ermilov.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
11887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
119480565d5SRuslan Ermilov.Fn SPLAY_MIN NAME "SPLAY_HEAD *head"
12087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
121480565d5SRuslan Ermilov.Fn SPLAY_MAX NAME "SPLAY_HEAD *head"
12287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
123480565d5SRuslan Ermilov.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm"
12487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
12587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME"
12687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
12787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME"
128480565d5SRuslan Ermilov.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head"
12987f5f0ecSDag-Erling Smørgrav.Ft void
13087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT "SPLAY_HEAD *head"
13187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
132480565d5SRuslan Ermilov.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
13387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
134480565d5SRuslan Ermilov.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm"
135480565d5SRuslan Ermilov.Fn RB_PROTOTYPE NAME TYPE FIELD CMP
136d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP
13751782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT NAME TYPE ATTR
13851782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR
13951782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE NAME TYPE ATTR
14051782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR
14151782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_FIND NAME TYPE ATTR
14251782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NFIND NAME TYPE ATTR
14351782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NEXT NAME TYPE ATTR
14451782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_PREV NAME TYPE ATTR
14551782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_MINMAX NAME TYPE ATTR
14622823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_REINSERT NAME TYPE ATTR
147480565d5SRuslan Ermilov.Fn RB_GENERATE NAME TYPE FIELD CMP
148d72cd779SJason Evans.Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP
14951782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR
15051782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR
15151782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE NAME TYPE FIELD ATTR
15251782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR
15351782e3aSKonstantin Belousov.Fn RB_GENERATE_FIND NAME TYPE FIELD CMP ATTR
15451782e3aSKonstantin Belousov.Fn RB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR
15551782e3aSKonstantin Belousov.Fn RB_GENERATE_NEXT NAME TYPE FIELD ATTR
15651782e3aSKonstantin Belousov.Fn RB_GENERATE_PREV NAME TYPE FIELD ATTR
15751782e3aSKonstantin Belousov.Fn RB_GENERATE_MINMAX NAME TYPE FIELD ATTR
15822823764SEdward Tomasz Napierala.Fn RB_GENERATE_REINSERT NAME TYPE FIELD CMP ATTR
159480565d5SRuslan Ermilov.Fn RB_ENTRY TYPE
160480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
16187f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER "RB_HEAD *head"
16287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
16387f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT "RB_HEAD *head"
16487f5f0ecSDag-Erling Smørgrav.Ft "bool"
16587f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY "RB_HEAD *head"
16687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
167480565d5SRuslan Ermilov.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm"
16887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
1698e4fd0a1SJason Evans.Fn RB_PREV NAME "RB_HEAD *head" "struct TYPE *elm"
1708e4fd0a1SJason Evans.Ft "struct TYPE *"
171480565d5SRuslan Ermilov.Fn RB_MIN NAME "RB_HEAD *head"
17287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
173480565d5SRuslan Ermilov.Fn RB_MAX NAME "RB_HEAD *head"
17487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
175480565d5SRuslan Ermilov.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm"
17687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
17706115e08SJason Evans.Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm"
17806115e08SJason Evans.Ft "struct TYPE *"
17987f5f0ecSDag-Erling Smørgrav.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME"
18087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
18187f5f0ecSDag-Erling Smørgrav.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME"
18287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
18387f5f0ecSDag-Erling Smørgrav.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
184480565d5SRuslan Ermilov.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head"
185639bf7bdSBruce M Simpson.Fn RB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME"
1869dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
1878e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head"
188639bf7bdSBruce M Simpson.Fn RB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME"
1899dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
19087f5f0ecSDag-Erling Smørgrav.Ft void
19187f5f0ecSDag-Erling Smørgrav.Fn RB_INIT "RB_HEAD *head"
19287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
193480565d5SRuslan Ermilov.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm"
19487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
195480565d5SRuslan Ermilov.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm"
19622823764SEdward Tomasz Napierala.Ft "struct TYPE *"
19722823764SEdward Tomasz Napierala.Fn RB_REINSERT NAME "RB_HEAD *head" "struct TYPE *elm"
198a8380d27SDoug Moore.Ft "void"
199a8380d27SDoug Moore.Fn RB_AUGMENT NAME "struct TYPE *elm"
20035557a0dSDoug Moore.Ft "void"
20135557a0dSDoug Moore.Fn RB_UPDATE_AUGMENT NAME "struct TYPE *elm"
20287f5f0ecSDag-Erling Smørgrav.Sh DESCRIPTION
203480565d5SRuslan ErmilovThese macros define data structures for different types of trees:
204e605dcc9SDoug Mooresplay trees and rank-balanced (wavl) trees.
20587f5f0ecSDag-Erling Smørgrav.Pp
20687f5f0ecSDag-Erling SmørgravIn the macro definitions,
20787f5f0ecSDag-Erling Smørgrav.Fa TYPE
20887f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must contain a field of type
209480565d5SRuslan Ermilov.Vt SPLAY_ENTRY ,
21087f5f0ecSDag-Erling Smørgravor
211480565d5SRuslan Ermilov.Vt RB_ENTRY ,
21287f5f0ecSDag-Erling Smørgravnamed
21387f5f0ecSDag-Erling Smørgrav.Fa ENTRYNAME .
21487f5f0ecSDag-Erling SmørgravThe argument
21587f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
21687f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must be declared
21787f5f0ecSDag-Erling Smørgravusing the macros
21887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD ,
21987f5f0ecSDag-Erling Smørgravor
22087f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD .
22187f5f0ecSDag-Erling SmørgravThe argument
22287f5f0ecSDag-Erling Smørgrav.Fa NAME
22387f5f0ecSDag-Erling Smørgravhas to be a unique name prefix for every tree that is defined.
22487f5f0ecSDag-Erling Smørgrav.Pp
225d72cd779SJason EvansThe function prototypes are declared with
226480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE ,
227d72cd779SJason Evans.Fn RB_PROTOTYPE ,
22887f5f0ecSDag-Erling Smørgravor
229d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC .
230d72cd779SJason EvansThe function bodies are generated with
231480565d5SRuslan Ermilov.Fn SPLAY_GENERATE ,
232d72cd779SJason Evans.Fn RB_GENERATE ,
23387f5f0ecSDag-Erling Smørgravor
234d72cd779SJason Evans.Fn RB_GENERATE_STATIC .
23587f5f0ecSDag-Erling SmørgravSee the examples below for further explanation of how these macros are used.
23687f5f0ecSDag-Erling Smørgrav.Sh SPLAY TREES
237480565d5SRuslan ErmilovA splay tree is a self-organizing data structure.
238480565d5SRuslan ErmilovEvery operation on the tree causes a splay to happen.
239480565d5SRuslan ErmilovThe splay moves the requested
24087f5f0ecSDag-Erling Smørgravnode to the root of the tree and partly rebalances it.
24187f5f0ecSDag-Erling Smørgrav.Pp
24287f5f0ecSDag-Erling SmørgravThis has the benefit that request locality causes faster lookups as
243480565d5SRuslan Ermilovthe requested nodes move to the top of the tree.
244480565d5SRuslan ErmilovOn the other hand, every lookup causes memory writes.
24587f5f0ecSDag-Erling Smørgrav.Pp
246480565d5SRuslan ErmilovThe Balance Theorem bounds the total access time for
247480565d5SRuslan Ermilov.Ar m
248480565d5SRuslan Ermilovoperations and
249480565d5SRuslan Ermilov.Ar n
250480565d5SRuslan Ermilovinserts on an initially empty tree as
251480565d5SRuslan Ermilov.Fn O "\*[lp]m + n\*[rp]lg n" .
252480565d5SRuslan ErmilovThe
253480565d5SRuslan Ermilovamortized cost for a sequence of
254480565d5SRuslan Ermilov.Ar m
255480565d5SRuslan Ermilovaccesses to a splay tree is
256480565d5SRuslan Ermilov.Fn O "lg n" .
25787f5f0ecSDag-Erling Smørgrav.Pp
25887f5f0ecSDag-Erling SmørgravA splay tree is headed by a structure defined by the
25987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD
26087f5f0ecSDag-Erling Smørgravmacro.
26187f5f0ecSDag-Erling SmørgravA
26287f5f0ecSDag-Erling Smørgravstructure is declared as follows:
263480565d5SRuslan Ermilov.Bd -ragged -offset indent
264480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
265480565d5SRuslan Ermilov.Va head ;
26687f5f0ecSDag-Erling Smørgrav.Ed
26787f5f0ecSDag-Erling Smørgrav.Pp
26887f5f0ecSDag-Erling Smørgravwhere
26987f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
27087f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct
27187f5f0ecSDag-Erling Smørgrav.Fa TYPE
27287f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree.
27387f5f0ecSDag-Erling Smørgrav.Pp
27487f5f0ecSDag-Erling SmørgravThe
27587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY
27687f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree.
27787f5f0ecSDag-Erling Smørgrav.Pp
27887f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure,
27987f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the
28087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE
28187f5f0ecSDag-Erling Smørgravmacro,
28287f5f0ecSDag-Erling Smørgravwhere
28387f5f0ecSDag-Erling Smørgrav.Fa NAME
28487f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree.
28587f5f0ecSDag-Erling SmørgravThe
28687f5f0ecSDag-Erling Smørgrav.Fa TYPE
28787f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed
28887f5f0ecSDag-Erling Smørgravby the tree.
28987f5f0ecSDag-Erling SmørgravThe
29087f5f0ecSDag-Erling Smørgrav.Fa FIELD
29187f5f0ecSDag-Erling Smørgravargument is the name of the element defined by
29287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY .
29387f5f0ecSDag-Erling Smørgrav.Pp
29487f5f0ecSDag-Erling SmørgravThe function bodies are generated with the
29587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_GENERATE
296480565d5SRuslan Ermilovmacro.
297480565d5SRuslan ErmilovIt takes the same arguments as the
29887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE
29987f5f0ecSDag-Erling Smørgravmacro, but should be used only once.
30087f5f0ecSDag-Erling Smørgrav.Pp
30187f5f0ecSDag-Erling SmørgravFinally,
30287f5f0ecSDag-Erling Smørgravthe
30387f5f0ecSDag-Erling Smørgrav.Fa CMP
304480565d5SRuslan Ermilovargument is the name of a function used to compare tree nodes
305480565d5SRuslan Ermilovwith each other.
306480565d5SRuslan ErmilovThe function takes two arguments of type
307480565d5SRuslan Ermilov.Vt "struct TYPE *" .
30887f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a
309480565d5SRuslan Ermilovvalue smaller than zero.
310480565d5SRuslan ErmilovIf they are equal, the function returns zero.
311480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero.
312480565d5SRuslan ErmilovThe compare
31387f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements.
31487f5f0ecSDag-Erling Smørgrav.Pp
31587f5f0ecSDag-Erling SmørgravThe
31687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT
31787f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by
31887f5f0ecSDag-Erling Smørgrav.Fa head .
31987f5f0ecSDag-Erling Smørgrav.Pp
32087f5f0ecSDag-Erling SmørgravThe splay tree can also be initialized statically by using the
32187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER
32287f5f0ecSDag-Erling Smørgravmacro like this:
323480565d5SRuslan Ermilov.Bd -ragged -offset indent
324480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
325480565d5SRuslan Ermilov.Va head
326480565d5SRuslan Ermilov=
327480565d5SRuslan Ermilov.Fn SPLAY_INITIALIZER &head ;
32887f5f0ecSDag-Erling Smørgrav.Ed
32987f5f0ecSDag-Erling Smørgrav.Pp
33087f5f0ecSDag-Erling SmørgravThe
33187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT
33287f5f0ecSDag-Erling Smørgravmacro inserts the new element
33387f5f0ecSDag-Erling Smørgrav.Fa elm
33487f5f0ecSDag-Erling Smørgravinto the tree.
33587f5f0ecSDag-Erling Smørgrav.Pp
33687f5f0ecSDag-Erling SmørgravThe
33787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE
33887f5f0ecSDag-Erling Smørgravmacro removes the element
33987f5f0ecSDag-Erling Smørgrav.Fa elm
34087f5f0ecSDag-Erling Smørgravfrom the tree pointed by
34187f5f0ecSDag-Erling Smørgrav.Fa head .
34287f5f0ecSDag-Erling Smørgrav.Pp
34387f5f0ecSDag-Erling SmørgravThe
34487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FIND
34587f5f0ecSDag-Erling Smørgravmacro can be used to find a particular element in the tree.
34687f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
34787f5f0ecSDag-Erling Smørgravstruct TYPE find, *res;
34887f5f0ecSDag-Erling Smørgravfind.key = 30;
34987f5f0ecSDag-Erling Smørgravres = SPLAY_FIND(NAME, head, &find);
35087f5f0ecSDag-Erling Smørgrav.Ed
35187f5f0ecSDag-Erling Smørgrav.Pp
35287f5f0ecSDag-Erling SmørgravThe
35387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT ,
35487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MIN ,
35587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MAX ,
35687f5f0ecSDag-Erling Smørgravand
35787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_NEXT
35887f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree:
35987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
36087f5f0ecSDag-Erling Smørgravfor (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np))
36187f5f0ecSDag-Erling Smørgrav.Ed
36287f5f0ecSDag-Erling Smørgrav.Pp
36387f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the
36487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FOREACH
36587f5f0ecSDag-Erling Smørgravmacro:
366480565d5SRuslan Ermilov.Bd -ragged -offset indent
367480565d5SRuslan Ermilov.Fn SPLAY_FOREACH np NAME head
36887f5f0ecSDag-Erling Smørgrav.Ed
36987f5f0ecSDag-Erling Smørgrav.Pp
37087f5f0ecSDag-Erling SmørgravThe
37187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY
37287f5f0ecSDag-Erling Smørgravmacro should be used to check whether a splay tree is empty.
373e605dcc9SDoug Moore.Sh RANK-BALANCED TREES
374e605dcc9SDoug MooreRank-balanced (RB) trees are a framework for defining height-balanced
375e605dcc9SDoug Moorebinary search trees, including AVL and red-black trees.
376e605dcc9SDoug MooreEach tree node has an associated rank.
377e605dcc9SDoug MooreBalance conditions are expressed by conditions on the differences in
378e605dcc9SDoug Moorerank between any node and its children.
379e605dcc9SDoug MooreRank differences are stored in each tree node.
38087f5f0ecSDag-Erling Smørgrav.Pp
381e605dcc9SDoug MooreThe balance conditions implemented by the RB macros lead to weak AVL
382e605dcc9SDoug Moore(wavl) trees, which combine the best aspects of AVL and red-black
383e605dcc9SDoug Mooretrees.
384e605dcc9SDoug MooreWavl trees rebalance after an insertion in the same way AVL trees do,
385e605dcc9SDoug Moorewith the same worst-case time as red-black trees offer, and with
386e605dcc9SDoug Moorebetter balance in the resulting tree.
387e605dcc9SDoug MooreWavl trees rebalance after a removal in a way that requires less
388e605dcc9SDoug Moorerestructuring, in the worst case, than either AVL or red-black trees
38958f5de0dSMateusz Piotrowskido.
39058f5de0dSMateusz PiotrowskiRemovals can lead to a tree almost as unbalanced as a red-black
391e605dcc9SDoug Mooretree; insertions lead to a tree becoming as balanced as an AVL tree.
39287f5f0ecSDag-Erling Smørgrav.Pp
393e605dcc9SDoug MooreA rank-balanced tree is headed by a structure defined by the
39487f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD
39587f5f0ecSDag-Erling Smørgravmacro.
39687f5f0ecSDag-Erling SmørgravA
39787f5f0ecSDag-Erling Smørgravstructure is declared as follows:
398480565d5SRuslan Ermilov.Bd -ragged -offset indent
399480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
400480565d5SRuslan Ermilov.Va head ;
40187f5f0ecSDag-Erling Smørgrav.Ed
40287f5f0ecSDag-Erling Smørgrav.Pp
40387f5f0ecSDag-Erling Smørgravwhere
40487f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
40587f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct
40687f5f0ecSDag-Erling Smørgrav.Fa TYPE
40787f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree.
40887f5f0ecSDag-Erling Smørgrav.Pp
40987f5f0ecSDag-Erling SmørgravThe
41087f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY
41187f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree.
41287f5f0ecSDag-Erling Smørgrav.Pp
41387f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure,
41487f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the
41587f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE
416d72cd779SJason Evansor
417d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC
41887f5f0ecSDag-Erling Smørgravmacro,
41987f5f0ecSDag-Erling Smørgravwhere
42087f5f0ecSDag-Erling Smørgrav.Fa NAME
42187f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree.
42287f5f0ecSDag-Erling SmørgravThe
42387f5f0ecSDag-Erling Smørgrav.Fa TYPE
42487f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed
42587f5f0ecSDag-Erling Smørgravby the tree.
42687f5f0ecSDag-Erling SmørgravThe
42787f5f0ecSDag-Erling Smørgrav.Fa FIELD
42887f5f0ecSDag-Erling Smørgravargument is the name of the element defined by
42987f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY .
43051782e3aSKonstantin BelousovIndividual prototypes can be declared with
43151782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT ,
43251782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT_COLOR ,
43351782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE ,
43451782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE_COLOR ,
43551782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_FIND ,
43651782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NFIND ,
43751782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NEXT ,
43851782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_PREV ,
43922823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_MINMAX ,
44051782e3aSKonstantin Belousovand
44122823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_REINSERT
442eb49a6d3SEdward Tomasz Napieralain case not all functions are required.
443eb49a6d3SEdward Tomasz NapieralaThe individual prototype macros expect
44451782e3aSKonstantin Belousov.Fa NAME ,
44551782e3aSKonstantin Belousov.Fa TYPE ,
44651782e3aSKonstantin Belousovand
44751782e3aSKonstantin Belousov.Fa ATTR
448eb49a6d3SEdward Tomasz Napieralaarguments.
449eb49a6d3SEdward Tomasz NapieralaThe
45051782e3aSKonstantin Belousov.Fa ATTR
45151782e3aSKonstantin Belousovargument must be empty for global functions or
45251782e3aSKonstantin Belousov.Fa static
45351782e3aSKonstantin Belousovfor static functions.
45487f5f0ecSDag-Erling Smørgrav.Pp
45587f5f0ecSDag-Erling SmørgravThe function bodies are generated with the
45687f5f0ecSDag-Erling Smørgrav.Fn RB_GENERATE
457d72cd779SJason Evansor
458d72cd779SJason Evans.Fn RB_GENERATE_STATIC
459480565d5SRuslan Ermilovmacro.
460d72cd779SJason EvansThese macros take the same arguments as the
46187f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE
462d72cd779SJason Evansand
463d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC
464d72cd779SJason Evansmacros, but should be used only once.
46551782e3aSKonstantin BelousovAs an alternative individual function bodies are generated with the
46651782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT ,
46751782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT_COLOR ,
46851782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE ,
46951782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE_COLOR ,
47051782e3aSKonstantin Belousov.Fn RB_GENERATE_FIND ,
47151782e3aSKonstantin Belousov.Fn RB_GENERATE_NFIND ,
47251782e3aSKonstantin Belousov.Fn RB_GENERATE_NEXT ,
47351782e3aSKonstantin Belousov.Fn RB_GENERATE_PREV ,
47422823764SEdward Tomasz Napierala.Fn RB_GENERATE_MINMAX ,
47551782e3aSKonstantin Belousovand
47622823764SEdward Tomasz Napierala.Fn RB_GENERATE_REINSERT
47751782e3aSKonstantin Belousovmacros.
47887f5f0ecSDag-Erling Smørgrav.Pp
47987f5f0ecSDag-Erling SmørgravFinally,
48087f5f0ecSDag-Erling Smørgravthe
48187f5f0ecSDag-Erling Smørgrav.Fa CMP
4829d44cd42SBenno Riceargument is the name of a function used to compare tree nodes
483480565d5SRuslan Ermilovwith each other.
484480565d5SRuslan ErmilovThe function takes two arguments of type
485480565d5SRuslan Ermilov.Vt "struct TYPE *" .
48687f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a
487480565d5SRuslan Ermilovvalue smaller than zero.
488480565d5SRuslan ErmilovIf they are equal, the function returns zero.
489480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero.
490480565d5SRuslan ErmilovThe compare
49187f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements.
49287f5f0ecSDag-Erling Smørgrav.Pp
49387f5f0ecSDag-Erling SmørgravThe
49487f5f0ecSDag-Erling Smørgrav.Fn RB_INIT
49587f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by
49687f5f0ecSDag-Erling Smørgrav.Fa head .
49787f5f0ecSDag-Erling Smørgrav.Pp
498e605dcc9SDoug MooreThe rank-balanced tree can also be initialized statically by using the
49987f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER
50087f5f0ecSDag-Erling Smørgravmacro like this:
501480565d5SRuslan Ermilov.Bd -ragged -offset indent
502480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
503480565d5SRuslan Ermilov.Va head
504480565d5SRuslan Ermilov=
505480565d5SRuslan Ermilov.Fn RB_INITIALIZER &head ;
50687f5f0ecSDag-Erling Smørgrav.Ed
50787f5f0ecSDag-Erling Smørgrav.Pp
50887f5f0ecSDag-Erling SmørgravThe
50987f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT
51087f5f0ecSDag-Erling Smørgravmacro inserts the new element
51187f5f0ecSDag-Erling Smørgrav.Fa elm
51287f5f0ecSDag-Erling Smørgravinto the tree.
51387f5f0ecSDag-Erling Smørgrav.Pp
51487f5f0ecSDag-Erling SmørgravThe
51587f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE
51687f5f0ecSDag-Erling Smørgravmacro removes the element
51787f5f0ecSDag-Erling Smørgrav.Fa elm
51887f5f0ecSDag-Erling Smørgravfrom the tree pointed by
51987f5f0ecSDag-Erling Smørgrav.Fa head .
52087f5f0ecSDag-Erling Smørgrav.Pp
52187f5f0ecSDag-Erling SmørgravThe
52287f5f0ecSDag-Erling Smørgrav.Fn RB_FIND
52306115e08SJason Evansand
52406115e08SJason Evans.Fn RB_NFIND
52506115e08SJason Evansmacros can be used to find a particular element in the tree.
526*08349b18SKonstantin Belousov.Pp
527*08349b18SKonstantin BelousovThe
528*08349b18SKonstantin Belousov.Fn RB_FIND
529*08349b18SKonstantin Belousovmacro returns the element in the tree equal to the provided
530*08349b18SKonstantin Belousovkey, or
531*08349b18SKonstantin Belousov.Dv NULL
532*08349b18SKonstantin Belousovif there is no such element.
533*08349b18SKonstantin Belousov.Pp
534*08349b18SKonstantin BelousovThe
535*08349b18SKonstantin Belousov.Fn RB_NFIND
536*08349b18SKonstantin Belousovmacro returns the least element greater than or equal to the provided
537*08349b18SKonstantin Belousovkey, or
538*08349b18SKonstantin Belousov.Dv NULL
539*08349b18SKonstantin Belousovif there is no such element.
54087f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
541*08349b18SKonstantin Belousovstruct TYPE find, *res, *resn;
54287f5f0ecSDag-Erling Smørgravfind.key = 30;
54387f5f0ecSDag-Erling Smørgravres = RB_FIND(NAME, head, &find);
544*08349b18SKonstantin Belousovresn = RB_NFIND(NAME, head, &find);
54587f5f0ecSDag-Erling Smørgrav.Ed
54687f5f0ecSDag-Erling Smørgrav.Pp
54787f5f0ecSDag-Erling SmørgravThe
54887f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT ,
54987f5f0ecSDag-Erling Smørgrav.Fn RB_MIN ,
55087f5f0ecSDag-Erling Smørgrav.Fn RB_MAX ,
5518e4fd0a1SJason Evans.Fn RB_NEXT ,
55287f5f0ecSDag-Erling Smørgravand
5538e4fd0a1SJason Evans.Fn RB_PREV
55487f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree:
555480565d5SRuslan Ermilov.Pp
556480565d5SRuslan Ermilov.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))"
55787f5f0ecSDag-Erling Smørgrav.Pp
55887f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the
55987f5f0ecSDag-Erling Smørgrav.Fn RB_FOREACH
5608e4fd0a1SJason Evansor
5618e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE
56287f5f0ecSDag-Erling Smørgravmacro:
563480565d5SRuslan Ermilov.Bd -ragged -offset indent
564480565d5SRuslan Ermilov.Fn RB_FOREACH np NAME head
56587f5f0ecSDag-Erling Smørgrav.Ed
56687f5f0ecSDag-Erling Smørgrav.Pp
5679dbae282SGleb SmirnoffThe macros
5689dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE
5699dbae282SGleb Smirnoffand
5709dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE
5719dbae282SGleb Smirnofftraverse the tree referenced by head
5729dbae282SGleb Smirnoffin a forward or reverse direction respectively,
5739dbae282SGleb Smirnoffassigning each element in turn to np.
5749dbae282SGleb SmirnoffHowever, unlike their unsafe counterparts,
5759dbae282SGleb Smirnoffthey permit both the removal of np
5769dbae282SGleb Smirnoffas well as freeing it from within the loop safely
5779dbae282SGleb Smirnoffwithout interfering with the traversal.
5789dbae282SGleb Smirnoff.Pp
579bff27689SBruce M SimpsonBoth
580bff27689SBruce M Simpson.Fn RB_FOREACH_FROM
581bff27689SBruce M Simpsonand
582bff27689SBruce M Simpson.Fn RB_FOREACH_REVERSE_FROM
583bff27689SBruce M Simpsonmay be used to continue an interrupted traversal
584bff27689SBruce M Simpsonin a forward or reverse direction respectively.
585639bf7bdSBruce M SimpsonThe head pointer is not required.
586639bf7bdSBruce M SimpsonThe pointer to the node from where to resume the traversal
587639bf7bdSBruce M Simpsonshould be passed as their last argument,
588bff27689SBruce M Simpsonand will be overwritten to provide safe traversal.
589bff27689SBruce M Simpson.Pp
59087f5f0ecSDag-Erling SmørgravThe
59187f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY
592e605dcc9SDoug Mooremacro should be used to check whether a rank-balanced tree is empty.
59322823764SEdward Tomasz Napierala.Pp
59422823764SEdward Tomasz NapieralaThe
59522823764SEdward Tomasz Napierala.Fn RB_REINSERT
59622823764SEdward Tomasz Napieralamacro updates the position of the element
59722823764SEdward Tomasz Napierala.Fa elm
59822823764SEdward Tomasz Napieralain the tree.
59922823764SEdward Tomasz NapieralaThis must be called if a member of a
60022823764SEdward Tomasz Napierala.Nm tree
60122823764SEdward Tomasz Napieralais modified in a way that affects comparison, such as by modifying
60222823764SEdward Tomasz Napieralaa node's key.
60322823764SEdward Tomasz NapieralaThis is a lower overhead alternative to removing the element
60422823764SEdward Tomasz Napieralaand reinserting it again.
605a8380d27SDoug Moore.Pp
606a8380d27SDoug MooreThe
607a8380d27SDoug Moore.Fn RB_AUGMENT
608a8380d27SDoug Mooremacro updates augmentation data of the element
609a8380d27SDoug Moore.Fa elm
610a8380d27SDoug Moorein the tree.
611a8380d27SDoug MooreBy default, it has no effect.
612a8380d27SDoug MooreIt is not meant to be invoked by the RB user.
61335557a0dSDoug MooreIf
61435557a0dSDoug Moore.Fn RB_AUGMENT
61535557a0dSDoug Mooreis defined by the RB user, then when an element is inserted or removed
61635557a0dSDoug Moorefrom the tree, it is invoked for every element in the tree that is the
61735557a0dSDoug Mooreroot of an altered subtree, working from the bottom of the tree up to
61835557a0dSDoug Moorethe top.
619a8380d27SDoug MooreIt is typically used to maintain some associative accumulation of tree
620a8380d27SDoug Mooreelements, such as sums, minima, maxima, and the like.
62135557a0dSDoug Moore.Pp
62235557a0dSDoug MooreThe
62335557a0dSDoug Moore.Fn RB_UPDATE_AUGMENT
62435557a0dSDoug Mooremacro updates augmentation data of the element
62535557a0dSDoug Moore.Fa elm
62635557a0dSDoug Mooreand its ancestors in the tree.
627624e5dc0SKonstantin BelousovIf
628624e5dc0SKonstantin Belousov.Fn RB_AUGMENT
629624e5dc0SKonstantin Belousovis defined by the RB user, then when an element in the
63035557a0dSDoug Mooretree is changed, without changing the order of items in the tree,
63135557a0dSDoug Mooreinvoking this function on that element restores consistency of the
63235557a0dSDoug Mooreaugmentation state of the tree as if the element had been removed and
63335557a0dSDoug Mooreinserted again.
634ac0879c3SEdward Tomasz Napierala.Sh EXAMPLES
635e605dcc9SDoug MooreThe following example demonstrates how to declare a rank-balanced tree
636ac0879c3SEdward Tomasz Napieralaholding integers.
637ac0879c3SEdward Tomasz NapieralaValues are inserted into it and the contents of the tree are printed
638ac0879c3SEdward Tomasz Napieralain order.
639a8380d27SDoug MooreTo maintain the sum of the values in the tree, each element maintains
640a8380d27SDoug Moorethe sum of its value and the sums from its left and right subtrees.
641ac0879c3SEdward Tomasz NapieralaLastly, the internal structure of the tree is printed.
642ac0879c3SEdward Tomasz Napierala.Bd -literal -offset 3n
643ac0879c3SEdward Tomasz Napierala#include <sys/tree.h>
644ac0879c3SEdward Tomasz Napierala#include <err.h>
645ac0879c3SEdward Tomasz Napierala#include <stdio.h>
646ac0879c3SEdward Tomasz Napierala#include <stdlib.h>
647ac0879c3SEdward Tomasz Napierala
648ac0879c3SEdward Tomasz Napieralastruct node {
649ac0879c3SEdward Tomasz Napierala	RB_ENTRY(node) entry;
650a8380d27SDoug Moore	int i, sum;
651ac0879c3SEdward Tomasz Napierala};
652ac0879c3SEdward Tomasz Napierala
653ac0879c3SEdward Tomasz Napieralaint
654ac0879c3SEdward Tomasz Napieralaintcmp(struct node *e1, struct node *e2)
655ac0879c3SEdward Tomasz Napierala{
656ac0879c3SEdward Tomasz Napierala	return (e1->i < e2->i ? -1 : e1->i > e2->i);
657ac0879c3SEdward Tomasz Napierala}
658ac0879c3SEdward Tomasz Napierala
659a8380d27SDoug Mooreint
660a8380d27SDoug Mooresumaug(struct node *e)
661a8380d27SDoug Moore{
662a8380d27SDoug Moore	e->sum = e->i;
663a8380d27SDoug Moore	if (RB_LEFT(e, entry) != NULL)
664a8380d27SDoug Moore		e->sum += RB_LEFT(e, entry)->sum;
665a8380d27SDoug Moore	if (RB_RIGHT(e, entry) != NULL)
666a8380d27SDoug Moore		e->sum += RB_RIGHT(e, entry)->sum;
667a8380d27SDoug Moore}
668a8380d27SDoug Moore#define RB_AUGMENT(entry) sumaug(entry)
669a8380d27SDoug Moore
670ac0879c3SEdward Tomasz NapieralaRB_HEAD(inttree, node) head = RB_INITIALIZER(&head);
671ac0879c3SEdward Tomasz NapieralaRB_GENERATE(inttree, node, entry, intcmp)
672ac0879c3SEdward Tomasz Napierala
673ac0879c3SEdward Tomasz Napieralaint testdata[] = {
674ac0879c3SEdward Tomasz Napierala	20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18,
675ac0879c3SEdward Tomasz Napierala	7, 11, 14
676ac0879c3SEdward Tomasz Napierala};
677ac0879c3SEdward Tomasz Napierala
678ac0879c3SEdward Tomasz Napieralavoid
679ac0879c3SEdward Tomasz Napieralaprint_tree(struct node *n)
680ac0879c3SEdward Tomasz Napierala{
681ac0879c3SEdward Tomasz Napierala	struct node *left, *right;
682ac0879c3SEdward Tomasz Napierala
683ac0879c3SEdward Tomasz Napierala	if (n == NULL) {
684ac0879c3SEdward Tomasz Napierala		printf("nil");
685ac0879c3SEdward Tomasz Napierala		return;
686ac0879c3SEdward Tomasz Napierala	}
687ac0879c3SEdward Tomasz Napierala	left = RB_LEFT(n, entry);
688ac0879c3SEdward Tomasz Napierala	right = RB_RIGHT(n, entry);
689ac0879c3SEdward Tomasz Napierala	if (left == NULL && right == NULL)
690ac0879c3SEdward Tomasz Napierala		printf("%d", n->i);
691ac0879c3SEdward Tomasz Napierala	else {
692ac0879c3SEdward Tomasz Napierala		printf("%d(", n->i);
693ac0879c3SEdward Tomasz Napierala		print_tree(left);
694ac0879c3SEdward Tomasz Napierala		printf(",");
695ac0879c3SEdward Tomasz Napierala		print_tree(right);
696ac0879c3SEdward Tomasz Napierala		printf(")");
697ac0879c3SEdward Tomasz Napierala	}
698ac0879c3SEdward Tomasz Napierala}
699ac0879c3SEdward Tomasz Napierala
700ac0879c3SEdward Tomasz Napieralaint
701ac0879c3SEdward Tomasz Napieralamain(void)
702ac0879c3SEdward Tomasz Napierala{
703ac0879c3SEdward Tomasz Napierala	int i;
704ac0879c3SEdward Tomasz Napierala	struct node *n;
705ac0879c3SEdward Tomasz Napierala
706ac0879c3SEdward Tomasz Napierala	for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) {
707ac0879c3SEdward Tomasz Napierala		if ((n = malloc(sizeof(struct node))) == NULL)
708ac0879c3SEdward Tomasz Napierala			err(1, NULL);
709ac0879c3SEdward Tomasz Napierala		n->i = testdata[i];
710ac0879c3SEdward Tomasz Napierala		RB_INSERT(inttree, &head, n);
711ac0879c3SEdward Tomasz Napierala	}
712ac0879c3SEdward Tomasz Napierala
713ac0879c3SEdward Tomasz Napierala	RB_FOREACH(n, inttree, &head) {
714ac0879c3SEdward Tomasz Napierala		printf("%d\en", n->i);
715ac0879c3SEdward Tomasz Napierala	}
716ac0879c3SEdward Tomasz Napierala	print_tree(RB_ROOT(&head));
717a8380d27SDoug Moore	printf("Sum of values = %d\n", RB_ROOT(&head)->sum);
718ac0879c3SEdward Tomasz Napierala	printf("\en");
719ac0879c3SEdward Tomasz Napierala	return (0);
720ac0879c3SEdward Tomasz Napierala}
721ac0879c3SEdward Tomasz Napierala.Ed
72287f5f0ecSDag-Erling Smørgrav.Sh NOTES
72387f5f0ecSDag-Erling SmørgravTrying to free a tree in the following way is a common error:
72487f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
72587f5f0ecSDag-Erling SmørgravSPLAY_FOREACH(var, NAME, head) {
72687f5f0ecSDag-Erling Smørgrav	SPLAY_REMOVE(NAME, head, var);
72787f5f0ecSDag-Erling Smørgrav	free(var);
72887f5f0ecSDag-Erling Smørgrav}
72987f5f0ecSDag-Erling Smørgravfree(head);
73087f5f0ecSDag-Erling Smørgrav.Ed
73187f5f0ecSDag-Erling Smørgrav.Pp
73287f5f0ecSDag-Erling SmørgravSince
73387f5f0ecSDag-Erling Smørgrav.Va var
734480565d5SRuslan Ermilovis freed, the
73587f5f0ecSDag-Erling Smørgrav.Fn FOREACH
73687f5f0ecSDag-Erling Smørgravmacro refers to a pointer that may have been reallocated already.
73787f5f0ecSDag-Erling SmørgravProper code needs a second variable.
73887f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
73987f5f0ecSDag-Erling Smørgravfor (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) {
74087f5f0ecSDag-Erling Smørgrav	nxt = SPLAY_NEXT(NAME, head, var);
74187f5f0ecSDag-Erling Smørgrav	SPLAY_REMOVE(NAME, head, var);
74287f5f0ecSDag-Erling Smørgrav	free(var);
74387f5f0ecSDag-Erling Smørgrav}
74487f5f0ecSDag-Erling Smørgrav.Ed
74587f5f0ecSDag-Erling Smørgrav.Pp
74687f5f0ecSDag-Erling SmørgravBoth
74787f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT
74887f5f0ecSDag-Erling Smørgravand
74987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT
75087f5f0ecSDag-Erling Smørgravreturn
751480565d5SRuslan Ermilov.Dv NULL
75287f5f0ecSDag-Erling Smørgravif the element was inserted in the tree successfully, otherwise they
75387f5f0ecSDag-Erling Smørgravreturn a pointer to the element with the colliding key.
75487f5f0ecSDag-Erling Smørgrav.Pp
75587f5f0ecSDag-Erling SmørgravAccordingly,
75687f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE
75787f5f0ecSDag-Erling Smørgravand
75887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE
75987f5f0ecSDag-Erling Smørgravreturn the pointer to the removed element otherwise they return
760480565d5SRuslan Ermilov.Dv NULL
76187f5f0ecSDag-Erling Smørgravto indicate an error.
762b9ec8f3bSSimon L. B. Nielsen.Sh SEE ALSO
763fad4b12bSEdward Tomasz Napierala.Xr arb 3 ,
764b9ec8f3bSSimon L. B. Nielsen.Xr queue 3
765e605dcc9SDoug Moore.Rs
766e605dcc9SDoug Moore.%A "Bernhard Haeupler"
767e605dcc9SDoug Moore.%A "Siddhartha Sen"
768e605dcc9SDoug Moore.%A "Robert E. Tarjan"
769e605dcc9SDoug Moore.%T "Rank-Balanced Trees"
770e605dcc9SDoug Moore.%U "http://sidsen.azurewebsites.net/papers/rb-trees-talg.pdf"
771e605dcc9SDoug Moore.%J "ACM Transactions on Algorithms"
772e605dcc9SDoug Moore.%V "11"
773e605dcc9SDoug Moore.%N "4"
774e605dcc9SDoug Moore.%D "June 2015"
775e605dcc9SDoug Moore.Re
776757a04bfSSergio Carlavilla Delgado.Sh HISTORY
777757a04bfSSergio Carlavilla DelgadoThe tree macros first appeared in
778757a04bfSSergio Carlavilla Delgado.Fx 4.6 .
77987f5f0ecSDag-Erling Smørgrav.Sh AUTHORS
780480565d5SRuslan ErmilovThe author of the tree macros is
781480565d5SRuslan Ermilov.An Niels Provos .
782