xref: /freebsd/share/man/man3/tree.3 (revision 503b7f94d831642308585c980a7cabe4470960d0)
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.\"
31*503b7f94SMaxim Konovalov.Dd August 2, 2024
3287f5f0ecSDag-Erling Smørgrav.Dt TREE 3
3387f5f0ecSDag-Erling Smørgrav.Os
3487f5f0ecSDag-Erling Smørgrav.Sh NAME
3587f5f0ecSDag-Erling Smørgrav.Nm SPLAY_PROTOTYPE ,
3687f5f0ecSDag-Erling Smørgrav.Nm SPLAY_GENERATE ,
3787f5f0ecSDag-Erling Smørgrav.Nm SPLAY_ENTRY ,
3887f5f0ecSDag-Erling Smørgrav.Nm SPLAY_HEAD ,
3987f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INITIALIZER ,
4087f5f0ecSDag-Erling Smørgrav.Nm SPLAY_ROOT ,
4187f5f0ecSDag-Erling Smørgrav.Nm SPLAY_EMPTY ,
4287f5f0ecSDag-Erling Smørgrav.Nm SPLAY_NEXT ,
4387f5f0ecSDag-Erling Smørgrav.Nm SPLAY_MIN ,
4487f5f0ecSDag-Erling Smørgrav.Nm SPLAY_MAX ,
4587f5f0ecSDag-Erling Smørgrav.Nm SPLAY_FIND ,
4687f5f0ecSDag-Erling Smørgrav.Nm SPLAY_LEFT ,
4787f5f0ecSDag-Erling Smørgrav.Nm SPLAY_RIGHT ,
4887f5f0ecSDag-Erling Smørgrav.Nm SPLAY_FOREACH ,
4987f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INIT ,
5087f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INSERT ,
5187f5f0ecSDag-Erling Smørgrav.Nm SPLAY_REMOVE ,
5287f5f0ecSDag-Erling Smørgrav.Nm RB_PROTOTYPE ,
53d72cd779SJason Evans.Nm RB_PROTOTYPE_STATIC ,
5451782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_INSERT ,
5551782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_INSERT_COLOR ,
5651782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_REMOVE ,
5751782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_REMOVE_COLOR ,
5851782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_FIND ,
5951782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_NFIND ,
6051782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_NEXT ,
6151782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_PREV ,
6251782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_MINMAX ,
6322823764SEdward Tomasz Napierala.Nm RB_PROTOTYPE_REINSERT ,
6487f5f0ecSDag-Erling Smørgrav.Nm RB_GENERATE ,
65d72cd779SJason Evans.Nm RB_GENERATE_STATIC ,
6651782e3aSKonstantin Belousov.Nm RB_GENERATE_INSERT ,
6751782e3aSKonstantin Belousov.Nm RB_GENERATE_INSERT_COLOR ,
6851782e3aSKonstantin Belousov.Nm RB_GENERATE_REMOVE ,
6951782e3aSKonstantin Belousov.Nm RB_GENERATE_REMOVE_COLOR ,
7051782e3aSKonstantin Belousov.Nm RB_GENERATE_FIND ,
7151782e3aSKonstantin Belousov.Nm RB_GENERATE_NFIND ,
7251782e3aSKonstantin Belousov.Nm RB_GENERATE_NEXT ,
7351782e3aSKonstantin Belousov.Nm RB_GENERATE_PREV ,
7451782e3aSKonstantin Belousov.Nm RB_GENERATE_MINMAX ,
7522823764SEdward Tomasz Napierala.Nm RB_GENERATE_REINSERT ,
7687f5f0ecSDag-Erling Smørgrav.Nm RB_ENTRY ,
7787f5f0ecSDag-Erling Smørgrav.Nm RB_HEAD ,
7887f5f0ecSDag-Erling Smørgrav.Nm RB_INITIALIZER ,
7987f5f0ecSDag-Erling Smørgrav.Nm RB_ROOT ,
8087f5f0ecSDag-Erling Smørgrav.Nm RB_EMPTY ,
8187f5f0ecSDag-Erling Smørgrav.Nm RB_NEXT ,
828e4fd0a1SJason Evans.Nm RB_PREV ,
8387f5f0ecSDag-Erling Smørgrav.Nm RB_MIN ,
8487f5f0ecSDag-Erling Smørgrav.Nm RB_MAX ,
8587f5f0ecSDag-Erling Smørgrav.Nm RB_FIND ,
8606115e08SJason Evans.Nm RB_NFIND ,
8787f5f0ecSDag-Erling Smørgrav.Nm RB_LEFT ,
8887f5f0ecSDag-Erling Smørgrav.Nm RB_RIGHT ,
8987f5f0ecSDag-Erling Smørgrav.Nm RB_PARENT ,
9087f5f0ecSDag-Erling Smørgrav.Nm RB_FOREACH ,
91bff27689SBruce M Simpson.Nm RB_FOREACH_FROM ,
929dbae282SGleb Smirnoff.Nm RB_FOREACH_SAFE ,
938e4fd0a1SJason Evans.Nm RB_FOREACH_REVERSE ,
94bff27689SBruce M Simpson.Nm RB_FOREACH_REVERSE_FROM ,
959dbae282SGleb Smirnoff.Nm RB_FOREACH_REVERSE_SAFE ,
9687f5f0ecSDag-Erling Smørgrav.Nm RB_INIT ,
9787f5f0ecSDag-Erling Smørgrav.Nm RB_INSERT ,
98368ee2f8SDoug Moore.Nm RB_INSERT_NEXT ,
99368ee2f8SDoug Moore.Nm RB_INSERT_PREV ,
10022823764SEdward Tomasz Napierala.Nm RB_REMOVE ,
101a8380d27SDoug Moore.Nm RB_REINSERT ,
102a8380d27SDoug Moore.Nm RB_AUGMENT
103b16f993eSDoug Moore.Nm RB_AUGMENT_CHECK,
10435557a0dSDoug Moore.Nm RB_UPDATE_AUGMENT
105e605dcc9SDoug Moore.Nd "implementations of splay and rank-balanced (wavl) trees"
10687f5f0ecSDag-Erling Smørgrav.Sh SYNOPSIS
107480565d5SRuslan Ermilov.In sys/tree.h
108480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP
109480565d5SRuslan Ermilov.Fn SPLAY_GENERATE NAME TYPE FIELD CMP
110480565d5SRuslan Ermilov.Fn SPLAY_ENTRY TYPE
111480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
11287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
11387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head"
11487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT "SPLAY_HEAD *head"
115480565d5SRuslan Ermilov.Ft bool
11687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY "SPLAY_HEAD *head"
11787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
118480565d5SRuslan Ermilov.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
11987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
120480565d5SRuslan Ermilov.Fn SPLAY_MIN NAME "SPLAY_HEAD *head"
12187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
122480565d5SRuslan Ermilov.Fn SPLAY_MAX NAME "SPLAY_HEAD *head"
12387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
124480565d5SRuslan Ermilov.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm"
12587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
12687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME"
12787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
12887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME"
129480565d5SRuslan Ermilov.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head"
13087f5f0ecSDag-Erling Smørgrav.Ft void
13187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT "SPLAY_HEAD *head"
13287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
133480565d5SRuslan Ermilov.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
13487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
135480565d5SRuslan Ermilov.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm"
136480565d5SRuslan Ermilov.Fn RB_PROTOTYPE NAME TYPE FIELD CMP
137d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP
13851782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT NAME TYPE ATTR
13951782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR
14051782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE NAME TYPE ATTR
14151782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR
14251782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_FIND NAME TYPE ATTR
14351782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NFIND NAME TYPE ATTR
14451782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NEXT NAME TYPE ATTR
14551782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_PREV NAME TYPE ATTR
14651782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_MINMAX NAME TYPE ATTR
14722823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_REINSERT NAME TYPE ATTR
148480565d5SRuslan Ermilov.Fn RB_GENERATE NAME TYPE FIELD CMP
149d72cd779SJason Evans.Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP
15051782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR
15151782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR
15251782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE NAME TYPE FIELD ATTR
15351782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR
15451782e3aSKonstantin Belousov.Fn RB_GENERATE_FIND NAME TYPE FIELD CMP ATTR
15551782e3aSKonstantin Belousov.Fn RB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR
15651782e3aSKonstantin Belousov.Fn RB_GENERATE_NEXT NAME TYPE FIELD ATTR
15751782e3aSKonstantin Belousov.Fn RB_GENERATE_PREV NAME TYPE FIELD ATTR
15851782e3aSKonstantin Belousov.Fn RB_GENERATE_MINMAX NAME TYPE FIELD ATTR
15922823764SEdward Tomasz Napierala.Fn RB_GENERATE_REINSERT NAME TYPE FIELD CMP ATTR
160480565d5SRuslan Ermilov.Fn RB_ENTRY TYPE
161480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
16287f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER "RB_HEAD *head"
16387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
16487f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT "RB_HEAD *head"
16587f5f0ecSDag-Erling Smørgrav.Ft "bool"
16687f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY "RB_HEAD *head"
16787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
168480565d5SRuslan Ermilov.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm"
16987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
1708e4fd0a1SJason Evans.Fn RB_PREV NAME "RB_HEAD *head" "struct TYPE *elm"
1718e4fd0a1SJason Evans.Ft "struct TYPE *"
172480565d5SRuslan Ermilov.Fn RB_MIN NAME "RB_HEAD *head"
17387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
174480565d5SRuslan Ermilov.Fn RB_MAX NAME "RB_HEAD *head"
17587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
176480565d5SRuslan Ermilov.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm"
17787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
17806115e08SJason Evans.Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm"
17906115e08SJason Evans.Ft "struct TYPE *"
18087f5f0ecSDag-Erling Smørgrav.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME"
18187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
18287f5f0ecSDag-Erling Smørgrav.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME"
18387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
18487f5f0ecSDag-Erling Smørgrav.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
185480565d5SRuslan Ermilov.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head"
186639bf7bdSBruce M Simpson.Fn RB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME"
1879dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
1888e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head"
189639bf7bdSBruce M Simpson.Fn RB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME"
1909dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
19187f5f0ecSDag-Erling Smørgrav.Ft void
19287f5f0ecSDag-Erling Smørgrav.Fn RB_INIT "RB_HEAD *head"
19387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
194480565d5SRuslan Ermilov.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm"
19587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *"
196368ee2f8SDoug Moore.Fn RB_INSERT_NEXT NAME "RB_HEAD *head" "struct TYPE *elm" "struct TYPE *next"
197368ee2f8SDoug Moore.Ft "struct TYPE *"
198368ee2f8SDoug Moore.Fn RB_INSERT_PREV NAME "RB_HEAD *head" "struct TYPE *elm" "struct TYPE *prev"
199368ee2f8SDoug Moore.Ft "struct TYPE *"
200480565d5SRuslan Ermilov.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm"
20122823764SEdward Tomasz Napierala.Ft "struct TYPE *"
20222823764SEdward Tomasz Napierala.Fn RB_REINSERT NAME "RB_HEAD *head" "struct TYPE *elm"
203a8380d27SDoug Moore.Ft "void"
204a8380d27SDoug Moore.Fn RB_AUGMENT NAME "struct TYPE *elm"
205b16f993eSDoug Moore.Ft "bool"
206b16f993eSDoug Moore.Fn RB_AUGMENT_CHECK NAME "struct TYPE *elm"
20735557a0dSDoug Moore.Ft "void"
20835557a0dSDoug Moore.Fn RB_UPDATE_AUGMENT NAME "struct TYPE *elm"
20987f5f0ecSDag-Erling Smørgrav.Sh DESCRIPTION
210480565d5SRuslan ErmilovThese macros define data structures for different types of trees:
211e605dcc9SDoug Mooresplay trees and rank-balanced (wavl) trees.
21287f5f0ecSDag-Erling Smørgrav.Pp
21387f5f0ecSDag-Erling SmørgravIn the macro definitions,
21487f5f0ecSDag-Erling Smørgrav.Fa TYPE
21587f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must contain a field of type
216480565d5SRuslan Ermilov.Vt SPLAY_ENTRY ,
21787f5f0ecSDag-Erling Smørgravor
218480565d5SRuslan Ermilov.Vt RB_ENTRY ,
21987f5f0ecSDag-Erling Smørgravnamed
22087f5f0ecSDag-Erling Smørgrav.Fa ENTRYNAME .
22187f5f0ecSDag-Erling SmørgravThe argument
22287f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
22387f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must be declared
22487f5f0ecSDag-Erling Smørgravusing the macros
22587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD ,
22687f5f0ecSDag-Erling Smørgravor
22787f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD .
22887f5f0ecSDag-Erling SmørgravThe argument
22987f5f0ecSDag-Erling Smørgrav.Fa NAME
23087f5f0ecSDag-Erling Smørgravhas to be a unique name prefix for every tree that is defined.
23187f5f0ecSDag-Erling Smørgrav.Pp
232d72cd779SJason EvansThe function prototypes are declared with
233480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE ,
234d72cd779SJason Evans.Fn RB_PROTOTYPE ,
23587f5f0ecSDag-Erling Smørgravor
236d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC .
237d72cd779SJason EvansThe function bodies are generated with
238480565d5SRuslan Ermilov.Fn SPLAY_GENERATE ,
239d72cd779SJason Evans.Fn RB_GENERATE ,
24087f5f0ecSDag-Erling Smørgravor
241d72cd779SJason Evans.Fn RB_GENERATE_STATIC .
24287f5f0ecSDag-Erling SmørgravSee the examples below for further explanation of how these macros are used.
24387f5f0ecSDag-Erling Smørgrav.Sh SPLAY TREES
244480565d5SRuslan ErmilovA splay tree is a self-organizing data structure.
245480565d5SRuslan ErmilovEvery operation on the tree causes a splay to happen.
246480565d5SRuslan ErmilovThe splay moves the requested
24787f5f0ecSDag-Erling Smørgravnode to the root of the tree and partly rebalances it.
24887f5f0ecSDag-Erling Smørgrav.Pp
24987f5f0ecSDag-Erling SmørgravThis has the benefit that request locality causes faster lookups as
250480565d5SRuslan Ermilovthe requested nodes move to the top of the tree.
251480565d5SRuslan ErmilovOn the other hand, every lookup causes memory writes.
25287f5f0ecSDag-Erling Smørgrav.Pp
253480565d5SRuslan ErmilovThe Balance Theorem bounds the total access time for
254480565d5SRuslan Ermilov.Ar m
255480565d5SRuslan Ermilovoperations and
256480565d5SRuslan Ermilov.Ar n
257480565d5SRuslan Ermilovinserts on an initially empty tree as
258480565d5SRuslan Ermilov.Fn O "\*[lp]m + n\*[rp]lg n" .
259480565d5SRuslan ErmilovThe
260480565d5SRuslan Ermilovamortized cost for a sequence of
261480565d5SRuslan Ermilov.Ar m
262480565d5SRuslan Ermilovaccesses to a splay tree is
263480565d5SRuslan Ermilov.Fn O "lg n" .
26487f5f0ecSDag-Erling Smørgrav.Pp
26587f5f0ecSDag-Erling SmørgravA splay tree is headed by a structure defined by the
26687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD
26787f5f0ecSDag-Erling Smørgravmacro.
26887f5f0ecSDag-Erling SmørgravA
26987f5f0ecSDag-Erling Smørgravstructure is declared as follows:
270480565d5SRuslan Ermilov.Bd -ragged -offset indent
271480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
272480565d5SRuslan Ermilov.Va head ;
27387f5f0ecSDag-Erling Smørgrav.Ed
27487f5f0ecSDag-Erling Smørgrav.Pp
27587f5f0ecSDag-Erling Smørgravwhere
27687f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
27787f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct
27887f5f0ecSDag-Erling Smørgrav.Fa TYPE
27987f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree.
28087f5f0ecSDag-Erling Smørgrav.Pp
28187f5f0ecSDag-Erling SmørgravThe
28287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY
28387f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree.
28487f5f0ecSDag-Erling Smørgrav.Pp
28587f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure,
28687f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the
28787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE
28887f5f0ecSDag-Erling Smørgravmacro,
28987f5f0ecSDag-Erling Smørgravwhere
29087f5f0ecSDag-Erling Smørgrav.Fa NAME
29187f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree.
29287f5f0ecSDag-Erling SmørgravThe
29387f5f0ecSDag-Erling Smørgrav.Fa TYPE
29487f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed
29587f5f0ecSDag-Erling Smørgravby the tree.
29687f5f0ecSDag-Erling SmørgravThe
29787f5f0ecSDag-Erling Smørgrav.Fa FIELD
29887f5f0ecSDag-Erling Smørgravargument is the name of the element defined by
29987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY .
30087f5f0ecSDag-Erling Smørgrav.Pp
30187f5f0ecSDag-Erling SmørgravThe function bodies are generated with the
30287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_GENERATE
303480565d5SRuslan Ermilovmacro.
304480565d5SRuslan ErmilovIt takes the same arguments as the
30587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE
30687f5f0ecSDag-Erling Smørgravmacro, but should be used only once.
30787f5f0ecSDag-Erling Smørgrav.Pp
30887f5f0ecSDag-Erling SmørgravFinally,
30987f5f0ecSDag-Erling Smørgravthe
31087f5f0ecSDag-Erling Smørgrav.Fa CMP
311480565d5SRuslan Ermilovargument is the name of a function used to compare tree nodes
312480565d5SRuslan Ermilovwith each other.
313480565d5SRuslan ErmilovThe function takes two arguments of type
314480565d5SRuslan Ermilov.Vt "struct TYPE *" .
31587f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a
316480565d5SRuslan Ermilovvalue smaller than zero.
317480565d5SRuslan ErmilovIf they are equal, the function returns zero.
318480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero.
319480565d5SRuslan ErmilovThe compare
32087f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements.
32187f5f0ecSDag-Erling Smørgrav.Pp
32287f5f0ecSDag-Erling SmørgravThe
32387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT
32487f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by
32587f5f0ecSDag-Erling Smørgrav.Fa head .
32687f5f0ecSDag-Erling Smørgrav.Pp
32787f5f0ecSDag-Erling SmørgravThe splay tree can also be initialized statically by using the
32887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER
32987f5f0ecSDag-Erling Smørgravmacro like this:
330480565d5SRuslan Ermilov.Bd -ragged -offset indent
331480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE
332480565d5SRuslan Ermilov.Va head
333480565d5SRuslan Ermilov=
334480565d5SRuslan Ermilov.Fn SPLAY_INITIALIZER &head ;
33587f5f0ecSDag-Erling Smørgrav.Ed
33687f5f0ecSDag-Erling Smørgrav.Pp
33787f5f0ecSDag-Erling SmørgravThe
33887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT
33987f5f0ecSDag-Erling Smørgravmacro inserts the new element
34087f5f0ecSDag-Erling Smørgrav.Fa elm
34187f5f0ecSDag-Erling Smørgravinto the tree.
34287f5f0ecSDag-Erling Smørgrav.Pp
34387f5f0ecSDag-Erling SmørgravThe
34487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE
34587f5f0ecSDag-Erling Smørgravmacro removes the element
34687f5f0ecSDag-Erling Smørgrav.Fa elm
34787f5f0ecSDag-Erling Smørgravfrom the tree pointed by
34887f5f0ecSDag-Erling Smørgrav.Fa head .
34987f5f0ecSDag-Erling Smørgrav.Pp
35087f5f0ecSDag-Erling SmørgravThe
35187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FIND
35287f5f0ecSDag-Erling Smørgravmacro can be used to find a particular element in the tree.
35387f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
35487f5f0ecSDag-Erling Smørgravstruct TYPE find, *res;
35587f5f0ecSDag-Erling Smørgravfind.key = 30;
35687f5f0ecSDag-Erling Smørgravres = SPLAY_FIND(NAME, head, &find);
35787f5f0ecSDag-Erling Smørgrav.Ed
35887f5f0ecSDag-Erling Smørgrav.Pp
35987f5f0ecSDag-Erling SmørgravThe
36087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT ,
36187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MIN ,
36287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MAX ,
36387f5f0ecSDag-Erling Smørgravand
36487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_NEXT
36587f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree:
36687f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
36787f5f0ecSDag-Erling Smørgravfor (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np))
36887f5f0ecSDag-Erling Smørgrav.Ed
36987f5f0ecSDag-Erling Smørgrav.Pp
37087f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the
37187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FOREACH
37287f5f0ecSDag-Erling Smørgravmacro:
373480565d5SRuslan Ermilov.Bd -ragged -offset indent
374480565d5SRuslan Ermilov.Fn SPLAY_FOREACH np NAME head
37587f5f0ecSDag-Erling Smørgrav.Ed
37687f5f0ecSDag-Erling Smørgrav.Pp
37787f5f0ecSDag-Erling SmørgravThe
37887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY
37987f5f0ecSDag-Erling Smørgravmacro should be used to check whether a splay tree is empty.
380e605dcc9SDoug Moore.Sh RANK-BALANCED TREES
381e605dcc9SDoug MooreRank-balanced (RB) trees are a framework for defining height-balanced
382e605dcc9SDoug Moorebinary search trees, including AVL and red-black trees.
383e605dcc9SDoug MooreEach tree node has an associated rank.
384e605dcc9SDoug MooreBalance conditions are expressed by conditions on the differences in
385e605dcc9SDoug Moorerank between any node and its children.
386e605dcc9SDoug MooreRank differences are stored in each tree node.
38787f5f0ecSDag-Erling Smørgrav.Pp
388e605dcc9SDoug MooreThe balance conditions implemented by the RB macros lead to weak AVL
389e605dcc9SDoug Moore(wavl) trees, which combine the best aspects of AVL and red-black
390e605dcc9SDoug Mooretrees.
391e605dcc9SDoug MooreWavl trees rebalance after an insertion in the same way AVL trees do,
392e605dcc9SDoug Moorewith the same worst-case time as red-black trees offer, and with
393e605dcc9SDoug Moorebetter balance in the resulting tree.
394e605dcc9SDoug MooreWavl trees rebalance after a removal in a way that requires less
395e605dcc9SDoug Moorerestructuring, in the worst case, than either AVL or red-black trees
39658f5de0dSMateusz Piotrowskido.
39758f5de0dSMateusz PiotrowskiRemovals can lead to a tree almost as unbalanced as a red-black
398e605dcc9SDoug Mooretree; insertions lead to a tree becoming as balanced as an AVL tree.
39987f5f0ecSDag-Erling Smørgrav.Pp
400e605dcc9SDoug MooreA rank-balanced tree is headed by a structure defined by the
40187f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD
40287f5f0ecSDag-Erling Smørgravmacro.
40387f5f0ecSDag-Erling SmørgravA
40487f5f0ecSDag-Erling Smørgravstructure is declared as follows:
405480565d5SRuslan Ermilov.Bd -ragged -offset indent
406480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
407480565d5SRuslan Ermilov.Va head ;
40887f5f0ecSDag-Erling Smørgrav.Ed
40987f5f0ecSDag-Erling Smørgrav.Pp
41087f5f0ecSDag-Erling Smørgravwhere
41187f5f0ecSDag-Erling Smørgrav.Fa HEADNAME
41287f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct
41387f5f0ecSDag-Erling Smørgrav.Fa TYPE
41487f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree.
41587f5f0ecSDag-Erling Smørgrav.Pp
41687f5f0ecSDag-Erling SmørgravThe
41787f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY
41887f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree.
41987f5f0ecSDag-Erling Smørgrav.Pp
42087f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure,
42187f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the
42287f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE
423d72cd779SJason Evansor
424d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC
42587f5f0ecSDag-Erling Smørgravmacro,
42687f5f0ecSDag-Erling Smørgravwhere
42787f5f0ecSDag-Erling Smørgrav.Fa NAME
42887f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree.
42987f5f0ecSDag-Erling SmørgravThe
43087f5f0ecSDag-Erling Smørgrav.Fa TYPE
43187f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed
43287f5f0ecSDag-Erling Smørgravby the tree.
43387f5f0ecSDag-Erling SmørgravThe
43487f5f0ecSDag-Erling Smørgrav.Fa FIELD
43587f5f0ecSDag-Erling Smørgravargument is the name of the element defined by
43687f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY .
43751782e3aSKonstantin BelousovIndividual prototypes can be declared with
43851782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT ,
43951782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT_COLOR ,
44051782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE ,
44151782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE_COLOR ,
44251782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_FIND ,
44351782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NFIND ,
44451782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NEXT ,
44551782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_PREV ,
44622823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_MINMAX ,
44751782e3aSKonstantin Belousovand
44822823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_REINSERT
449eb49a6d3SEdward Tomasz Napieralain case not all functions are required.
450eb49a6d3SEdward Tomasz NapieralaThe individual prototype macros expect
45151782e3aSKonstantin Belousov.Fa NAME ,
45251782e3aSKonstantin Belousov.Fa TYPE ,
45351782e3aSKonstantin Belousovand
45451782e3aSKonstantin Belousov.Fa ATTR
455eb49a6d3SEdward Tomasz Napieralaarguments.
456eb49a6d3SEdward Tomasz NapieralaThe
45751782e3aSKonstantin Belousov.Fa ATTR
45851782e3aSKonstantin Belousovargument must be empty for global functions or
45951782e3aSKonstantin Belousov.Fa static
46051782e3aSKonstantin Belousovfor static functions.
46187f5f0ecSDag-Erling Smørgrav.Pp
46287f5f0ecSDag-Erling SmørgravThe function bodies are generated with the
46387f5f0ecSDag-Erling Smørgrav.Fn RB_GENERATE
464d72cd779SJason Evansor
465d72cd779SJason Evans.Fn RB_GENERATE_STATIC
466480565d5SRuslan Ermilovmacro.
467d72cd779SJason EvansThese macros take the same arguments as the
46887f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE
469d72cd779SJason Evansand
470d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC
471d72cd779SJason Evansmacros, but should be used only once.
47251782e3aSKonstantin BelousovAs an alternative individual function bodies are generated with the
47351782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT ,
47451782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT_COLOR ,
47551782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE ,
47651782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE_COLOR ,
47751782e3aSKonstantin Belousov.Fn RB_GENERATE_FIND ,
47851782e3aSKonstantin Belousov.Fn RB_GENERATE_NFIND ,
47951782e3aSKonstantin Belousov.Fn RB_GENERATE_NEXT ,
48051782e3aSKonstantin Belousov.Fn RB_GENERATE_PREV ,
48122823764SEdward Tomasz Napierala.Fn RB_GENERATE_MINMAX ,
48251782e3aSKonstantin Belousovand
48322823764SEdward Tomasz Napierala.Fn RB_GENERATE_REINSERT
48451782e3aSKonstantin Belousovmacros.
48587f5f0ecSDag-Erling Smørgrav.Pp
48687f5f0ecSDag-Erling SmørgravFinally,
48787f5f0ecSDag-Erling Smørgravthe
48887f5f0ecSDag-Erling Smørgrav.Fa CMP
4899d44cd42SBenno Riceargument is the name of a function used to compare tree nodes
490480565d5SRuslan Ermilovwith each other.
491480565d5SRuslan ErmilovThe function takes two arguments of type
492480565d5SRuslan Ermilov.Vt "struct TYPE *" .
49387f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a
494480565d5SRuslan Ermilovvalue smaller than zero.
495480565d5SRuslan ErmilovIf they are equal, the function returns zero.
496480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero.
497480565d5SRuslan ErmilovThe compare
49887f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements.
49987f5f0ecSDag-Erling Smørgrav.Pp
50087f5f0ecSDag-Erling SmørgravThe
50187f5f0ecSDag-Erling Smørgrav.Fn RB_INIT
50287f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by
50387f5f0ecSDag-Erling Smørgrav.Fa head .
50487f5f0ecSDag-Erling Smørgrav.Pp
505e605dcc9SDoug MooreThe rank-balanced tree can also be initialized statically by using the
50687f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER
50787f5f0ecSDag-Erling Smørgravmacro like this:
508480565d5SRuslan Ermilov.Bd -ragged -offset indent
509480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE
510480565d5SRuslan Ermilov.Va head
511480565d5SRuslan Ermilov=
512480565d5SRuslan Ermilov.Fn RB_INITIALIZER &head ;
51387f5f0ecSDag-Erling Smørgrav.Ed
51487f5f0ecSDag-Erling Smørgrav.Pp
51587f5f0ecSDag-Erling SmørgravThe
51687f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT
51787f5f0ecSDag-Erling Smørgravmacro inserts the new element
51887f5f0ecSDag-Erling Smørgrav.Fa elm
51987f5f0ecSDag-Erling Smørgravinto the tree.
52087f5f0ecSDag-Erling Smørgrav.Pp
52187f5f0ecSDag-Erling SmørgravThe
522368ee2f8SDoug Moore.Fn RB_INSERT_NEXT
523368ee2f8SDoug Mooremacro inserts the new element
524368ee2f8SDoug Moore.Fa elm
525368ee2f8SDoug Mooreinto the tree immediately after a given element.
526368ee2f8SDoug Moore.Pp
527368ee2f8SDoug MooreThe
528368ee2f8SDoug Moore.Fn RB_INSERT_PREV
529368ee2f8SDoug Mooremacro inserts the new element
530368ee2f8SDoug Moore.Fa elm
531368ee2f8SDoug Mooreinto the tree immediately before a given element.
532368ee2f8SDoug Moore.Pp
533368ee2f8SDoug MooreThe
53487f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE
53587f5f0ecSDag-Erling Smørgravmacro removes the element
53687f5f0ecSDag-Erling Smørgrav.Fa elm
53787f5f0ecSDag-Erling Smørgravfrom the tree pointed by
53887f5f0ecSDag-Erling Smørgrav.Fa head .
53987f5f0ecSDag-Erling Smørgrav.Pp
54087f5f0ecSDag-Erling SmørgravThe
54187f5f0ecSDag-Erling Smørgrav.Fn RB_FIND
54206115e08SJason Evansand
54306115e08SJason Evans.Fn RB_NFIND
54406115e08SJason Evansmacros can be used to find a particular element in the tree.
54508349b18SKonstantin Belousov.Pp
54608349b18SKonstantin BelousovThe
54708349b18SKonstantin Belousov.Fn RB_FIND
54808349b18SKonstantin Belousovmacro returns the element in the tree equal to the provided
54908349b18SKonstantin Belousovkey, or
55008349b18SKonstantin Belousov.Dv NULL
55108349b18SKonstantin Belousovif there is no such element.
55208349b18SKonstantin Belousov.Pp
55308349b18SKonstantin BelousovThe
55408349b18SKonstantin Belousov.Fn RB_NFIND
55508349b18SKonstantin Belousovmacro returns the least element greater than or equal to the provided
55608349b18SKonstantin Belousovkey, or
55708349b18SKonstantin Belousov.Dv NULL
55808349b18SKonstantin Belousovif there is no such element.
55987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
56008349b18SKonstantin Belousovstruct TYPE find, *res, *resn;
56187f5f0ecSDag-Erling Smørgravfind.key = 30;
56287f5f0ecSDag-Erling Smørgravres = RB_FIND(NAME, head, &find);
56308349b18SKonstantin Belousovresn = RB_NFIND(NAME, head, &find);
56487f5f0ecSDag-Erling Smørgrav.Ed
56587f5f0ecSDag-Erling Smørgrav.Pp
56687f5f0ecSDag-Erling SmørgravThe
56787f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT ,
56887f5f0ecSDag-Erling Smørgrav.Fn RB_MIN ,
56987f5f0ecSDag-Erling Smørgrav.Fn RB_MAX ,
5708e4fd0a1SJason Evans.Fn RB_NEXT ,
57187f5f0ecSDag-Erling Smørgravand
5728e4fd0a1SJason Evans.Fn RB_PREV
57387f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree:
574480565d5SRuslan Ermilov.Pp
575480565d5SRuslan Ermilov.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))"
57687f5f0ecSDag-Erling Smørgrav.Pp
57787f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the
57887f5f0ecSDag-Erling Smørgrav.Fn RB_FOREACH
5798e4fd0a1SJason Evansor
5808e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE
58187f5f0ecSDag-Erling Smørgravmacro:
582480565d5SRuslan Ermilov.Bd -ragged -offset indent
583480565d5SRuslan Ermilov.Fn RB_FOREACH np NAME head
58487f5f0ecSDag-Erling Smørgrav.Ed
58587f5f0ecSDag-Erling Smørgrav.Pp
5869dbae282SGleb SmirnoffThe macros
5879dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE
5889dbae282SGleb Smirnoffand
5899dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE
5909dbae282SGleb Smirnofftraverse the tree referenced by head
5919dbae282SGleb Smirnoffin a forward or reverse direction respectively,
5929dbae282SGleb Smirnoffassigning each element in turn to np.
5939dbae282SGleb SmirnoffHowever, unlike their unsafe counterparts,
5949dbae282SGleb Smirnoffthey permit both the removal of np
5959dbae282SGleb Smirnoffas well as freeing it from within the loop safely
5969dbae282SGleb Smirnoffwithout interfering with the traversal.
5979dbae282SGleb Smirnoff.Pp
598bff27689SBruce M SimpsonBoth
599bff27689SBruce M Simpson.Fn RB_FOREACH_FROM
600bff27689SBruce M Simpsonand
601bff27689SBruce M Simpson.Fn RB_FOREACH_REVERSE_FROM
602bff27689SBruce M Simpsonmay be used to continue an interrupted traversal
603bff27689SBruce M Simpsonin a forward or reverse direction respectively.
604639bf7bdSBruce M SimpsonThe head pointer is not required.
605639bf7bdSBruce M SimpsonThe pointer to the node from where to resume the traversal
606639bf7bdSBruce M Simpsonshould be passed as their last argument,
607bff27689SBruce M Simpsonand will be overwritten to provide safe traversal.
608bff27689SBruce M Simpson.Pp
60987f5f0ecSDag-Erling SmørgravThe
61087f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY
611e605dcc9SDoug Mooremacro should be used to check whether a rank-balanced tree is empty.
61222823764SEdward Tomasz Napierala.Pp
61322823764SEdward Tomasz NapieralaThe
61422823764SEdward Tomasz Napierala.Fn RB_REINSERT
61522823764SEdward Tomasz Napieralamacro updates the position of the element
61622823764SEdward Tomasz Napierala.Fa elm
61722823764SEdward Tomasz Napieralain the tree.
61822823764SEdward Tomasz NapieralaThis must be called if a member of a
61922823764SEdward Tomasz Napierala.Nm tree
62022823764SEdward Tomasz Napieralais modified in a way that affects comparison, such as by modifying
62122823764SEdward Tomasz Napieralaa node's key.
62222823764SEdward Tomasz NapieralaThis is a lower overhead alternative to removing the element
62322823764SEdward Tomasz Napieralaand reinserting it again.
624a8380d27SDoug Moore.Pp
625a8380d27SDoug MooreThe
626a8380d27SDoug Moore.Fn RB_AUGMENT
627a8380d27SDoug Mooremacro updates augmentation data of the element
628a8380d27SDoug Moore.Fa elm
629a8380d27SDoug Moorein the tree.
630a8380d27SDoug MooreBy default, it has no effect.
631a8380d27SDoug MooreIt is not meant to be invoked by the RB user.
63235557a0dSDoug MooreIf
63335557a0dSDoug Moore.Fn RB_AUGMENT
63435557a0dSDoug Mooreis defined by the RB user, then when an element is inserted or removed
63535557a0dSDoug Moorefrom the tree, it is invoked for every element in the tree that is the
63635557a0dSDoug Mooreroot of an altered subtree, working from the bottom of the tree up to
63735557a0dSDoug Moorethe top.
638a8380d27SDoug MooreIt is typically used to maintain some associative accumulation of tree
639a8380d27SDoug Mooreelements, such as sums, minima, maxima, and the like.
64035557a0dSDoug Moore.Pp
64135557a0dSDoug MooreThe
642b16f993eSDoug Moore.Fn RB_AUGMENT_CHECK
643b16f993eSDoug Mooremacro updates augmentation data of the element
644b16f993eSDoug Moore.Fa elm
645b16f993eSDoug Moorein the tree.
646b16f993eSDoug MooreBy default, it does nothing and returns false.
647b16f993eSDoug MooreIf
648b16f993eSDoug Moore.Fn RB_AUGMENT_CHECK
649b16f993eSDoug Mooreis defined, then when an element is inserted or removed from the tree,
650b16f993eSDoug Mooreit is invoked for every element in the tree that is the root of an
651b16f993eSDoug Moorealtered subtree, working from the bottom of the tree up toward the
652b16f993eSDoug Mooretop, until it returns false to indicate that it did not change the
653b16f993eSDoug Mooreelement and so working further up the tree would change nothing.
654b16f993eSDoug MooreIt is typically used to maintain some associative accumulation of tree
655b16f993eSDoug Mooreelements, such as sums, minima, maxima, and the like.
656b16f993eSDoug Moore.Pp
657b16f993eSDoug MooreThe
65835557a0dSDoug Moore.Fn RB_UPDATE_AUGMENT
65935557a0dSDoug Mooremacro updates augmentation data of the element
66035557a0dSDoug Moore.Fa elm
66135557a0dSDoug Mooreand its ancestors in the tree.
662624e5dc0SKonstantin BelousovIf
663624e5dc0SKonstantin Belousov.Fn RB_AUGMENT
664624e5dc0SKonstantin Belousovis defined by the RB user, then when an element in the
66535557a0dSDoug Mooretree is changed, without changing the order of items in the tree,
66635557a0dSDoug Mooreinvoking this function on that element restores consistency of the
66735557a0dSDoug Mooreaugmentation state of the tree as if the element had been removed and
66835557a0dSDoug Mooreinserted again.
669ac0879c3SEdward Tomasz Napierala.Sh EXAMPLES
670e605dcc9SDoug MooreThe following example demonstrates how to declare a rank-balanced tree
671ac0879c3SEdward Tomasz Napieralaholding integers.
672ac0879c3SEdward Tomasz NapieralaValues are inserted into it and the contents of the tree are printed
673ac0879c3SEdward Tomasz Napieralain order.
674a8380d27SDoug MooreTo maintain the sum of the values in the tree, each element maintains
675a8380d27SDoug Moorethe sum of its value and the sums from its left and right subtrees.
676ac0879c3SEdward Tomasz NapieralaLastly, the internal structure of the tree is printed.
677ac0879c3SEdward Tomasz Napierala.Bd -literal -offset 3n
678*503b7f94SMaxim Konovalov#define RB_AUGMENT(entry) sumaug(entry)
679*503b7f94SMaxim Konovalov
680ac0879c3SEdward Tomasz Napierala#include <sys/tree.h>
681ac0879c3SEdward Tomasz Napierala#include <err.h>
682ac0879c3SEdward Tomasz Napierala#include <stdio.h>
683ac0879c3SEdward Tomasz Napierala#include <stdlib.h>
684ac0879c3SEdward Tomasz Napierala
685ac0879c3SEdward Tomasz Napieralastruct node {
686ac0879c3SEdward Tomasz Napierala	RB_ENTRY(node) entry;
687a8380d27SDoug Moore	int i, sum;
688ac0879c3SEdward Tomasz Napierala};
689ac0879c3SEdward Tomasz Napierala
690ac0879c3SEdward Tomasz Napieralaint
691ac0879c3SEdward Tomasz Napieralaintcmp(struct node *e1, struct node *e2)
692ac0879c3SEdward Tomasz Napierala{
693ac0879c3SEdward Tomasz Napierala	return (e1->i < e2->i ? -1 : e1->i > e2->i);
694ac0879c3SEdward Tomasz Napierala}
695ac0879c3SEdward Tomasz Napierala
696*503b7f94SMaxim Konovalovvoid
697a8380d27SDoug Mooresumaug(struct node *e)
698a8380d27SDoug Moore{
699a8380d27SDoug Moore	e->sum = e->i;
700a8380d27SDoug Moore	if (RB_LEFT(e, entry) != NULL)
701a8380d27SDoug Moore		e->sum += RB_LEFT(e, entry)->sum;
702a8380d27SDoug Moore	if (RB_RIGHT(e, entry) != NULL)
703a8380d27SDoug Moore		e->sum += RB_RIGHT(e, entry)->sum;
704a8380d27SDoug Moore}
705a8380d27SDoug Moore
706ac0879c3SEdward Tomasz NapieralaRB_HEAD(inttree, node) head = RB_INITIALIZER(&head);
707ac0879c3SEdward Tomasz NapieralaRB_GENERATE(inttree, node, entry, intcmp)
708ac0879c3SEdward Tomasz Napierala
709ac0879c3SEdward Tomasz Napieralaint testdata[] = {
710ac0879c3SEdward Tomasz Napierala	20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18,
711ac0879c3SEdward Tomasz Napierala	7, 11, 14
712ac0879c3SEdward Tomasz Napierala};
713ac0879c3SEdward Tomasz Napierala
714ac0879c3SEdward Tomasz Napieralavoid
715ac0879c3SEdward Tomasz Napieralaprint_tree(struct node *n)
716ac0879c3SEdward Tomasz Napierala{
717ac0879c3SEdward Tomasz Napierala	struct node *left, *right;
718ac0879c3SEdward Tomasz Napierala
719ac0879c3SEdward Tomasz Napierala	if (n == NULL) {
720ac0879c3SEdward Tomasz Napierala		printf("nil");
721ac0879c3SEdward Tomasz Napierala		return;
722ac0879c3SEdward Tomasz Napierala	}
723ac0879c3SEdward Tomasz Napierala	left = RB_LEFT(n, entry);
724ac0879c3SEdward Tomasz Napierala	right = RB_RIGHT(n, entry);
725ac0879c3SEdward Tomasz Napierala	if (left == NULL && right == NULL)
726ac0879c3SEdward Tomasz Napierala		printf("%d", n->i);
727ac0879c3SEdward Tomasz Napierala	else {
728ac0879c3SEdward Tomasz Napierala		printf("%d(", n->i);
729ac0879c3SEdward Tomasz Napierala		print_tree(left);
730ac0879c3SEdward Tomasz Napierala		printf(",");
731ac0879c3SEdward Tomasz Napierala		print_tree(right);
732ac0879c3SEdward Tomasz Napierala		printf(")");
733ac0879c3SEdward Tomasz Napierala	}
734ac0879c3SEdward Tomasz Napierala}
735ac0879c3SEdward Tomasz Napierala
736ac0879c3SEdward Tomasz Napieralaint
737ac0879c3SEdward Tomasz Napieralamain(void)
738ac0879c3SEdward Tomasz Napierala{
739ac0879c3SEdward Tomasz Napierala	int i;
740ac0879c3SEdward Tomasz Napierala	struct node *n;
741ac0879c3SEdward Tomasz Napierala
742ac0879c3SEdward Tomasz Napierala	for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) {
743ac0879c3SEdward Tomasz Napierala		if ((n = malloc(sizeof(struct node))) == NULL)
744ac0879c3SEdward Tomasz Napierala			err(1, NULL);
745ac0879c3SEdward Tomasz Napierala		n->i = testdata[i];
746ac0879c3SEdward Tomasz Napierala		RB_INSERT(inttree, &head, n);
747ac0879c3SEdward Tomasz Napierala	}
748ac0879c3SEdward Tomasz Napierala
749ac0879c3SEdward Tomasz Napierala	RB_FOREACH(n, inttree, &head) {
750ac0879c3SEdward Tomasz Napierala		printf("%d\en", n->i);
751ac0879c3SEdward Tomasz Napierala	}
752ac0879c3SEdward Tomasz Napierala	print_tree(RB_ROOT(&head));
753*503b7f94SMaxim Konovalov	printf("\enSum of values = %d\en", RB_ROOT(&head)->sum);
754ac0879c3SEdward Tomasz Napierala	return (0);
755ac0879c3SEdward Tomasz Napierala}
756ac0879c3SEdward Tomasz Napierala.Ed
75787f5f0ecSDag-Erling Smørgrav.Sh NOTES
75887f5f0ecSDag-Erling SmørgravTrying to free a tree in the following way is a common error:
75987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
76087f5f0ecSDag-Erling SmørgravSPLAY_FOREACH(var, NAME, head) {
76187f5f0ecSDag-Erling Smørgrav	SPLAY_REMOVE(NAME, head, var);
76287f5f0ecSDag-Erling Smørgrav	free(var);
76387f5f0ecSDag-Erling Smørgrav}
76487f5f0ecSDag-Erling Smørgravfree(head);
76587f5f0ecSDag-Erling Smørgrav.Ed
76687f5f0ecSDag-Erling Smørgrav.Pp
76787f5f0ecSDag-Erling SmørgravSince
76887f5f0ecSDag-Erling Smørgrav.Va var
769480565d5SRuslan Ermilovis freed, the
77087f5f0ecSDag-Erling Smørgrav.Fn FOREACH
77187f5f0ecSDag-Erling Smørgravmacro refers to a pointer that may have been reallocated already.
77287f5f0ecSDag-Erling SmørgravProper code needs a second variable.
77387f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent
77487f5f0ecSDag-Erling Smørgravfor (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) {
77587f5f0ecSDag-Erling Smørgrav	nxt = SPLAY_NEXT(NAME, head, var);
77687f5f0ecSDag-Erling Smørgrav	SPLAY_REMOVE(NAME, head, var);
77787f5f0ecSDag-Erling Smørgrav	free(var);
77887f5f0ecSDag-Erling Smørgrav}
77987f5f0ecSDag-Erling Smørgrav.Ed
78087f5f0ecSDag-Erling Smørgrav.Pp
78187f5f0ecSDag-Erling SmørgravBoth
78287f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT
78387f5f0ecSDag-Erling Smørgravand
78487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT
78587f5f0ecSDag-Erling Smørgravreturn
786480565d5SRuslan Ermilov.Dv NULL
78787f5f0ecSDag-Erling Smørgravif the element was inserted in the tree successfully, otherwise they
78887f5f0ecSDag-Erling Smørgravreturn a pointer to the element with the colliding key.
78987f5f0ecSDag-Erling Smørgrav.Pp
79087f5f0ecSDag-Erling SmørgravAccordingly,
79187f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE
79287f5f0ecSDag-Erling Smørgravand
79387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE
79487f5f0ecSDag-Erling Smørgravreturn the pointer to the removed element otherwise they return
795480565d5SRuslan Ermilov.Dv NULL
79687f5f0ecSDag-Erling Smørgravto indicate an error.
797b9ec8f3bSSimon L. B. Nielsen.Sh SEE ALSO
798fad4b12bSEdward Tomasz Napierala.Xr arb 3 ,
799b9ec8f3bSSimon L. B. Nielsen.Xr queue 3
800e605dcc9SDoug Moore.Rs
801e605dcc9SDoug Moore.%A "Bernhard Haeupler"
802e605dcc9SDoug Moore.%A "Siddhartha Sen"
803e605dcc9SDoug Moore.%A "Robert E. Tarjan"
804e605dcc9SDoug Moore.%T "Rank-Balanced Trees"
805e605dcc9SDoug Moore.%U "http://sidsen.azurewebsites.net/papers/rb-trees-talg.pdf"
806e605dcc9SDoug Moore.%J "ACM Transactions on Algorithms"
807e605dcc9SDoug Moore.%V "11"
808e605dcc9SDoug Moore.%N "4"
809e605dcc9SDoug Moore.%D "June 2015"
810e605dcc9SDoug Moore.Re
811757a04bfSSergio Carlavilla Delgado.Sh HISTORY
812757a04bfSSergio Carlavilla DelgadoThe tree macros first appeared in
813757a04bfSSergio Carlavilla Delgado.Fx 4.6 .
81487f5f0ecSDag-Erling Smørgrav.Sh AUTHORS
815480565d5SRuslan ErmilovThe author of the tree macros is
816480565d5SRuslan Ermilov.An Niels Provos .
817