187f5f0ecSDag-Erling Smørgrav.\" $OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $ 2480565d5SRuslan Ermilov.\" 3480565d5SRuslan Ermilov.\" Copyright 2002 Niels Provos <provos@citi.umich.edu> 4480565d5SRuslan Ermilov.\" All rights reserved. 5480565d5SRuslan Ermilov.\" 6480565d5SRuslan Ermilov.\" Redistribution and use in source and binary forms, with or without 7480565d5SRuslan Ermilov.\" modification, are permitted provided that the following conditions 8480565d5SRuslan Ermilov.\" are met: 9480565d5SRuslan Ermilov.\" 1. Redistributions of source code must retain the above copyright 10480565d5SRuslan Ermilov.\" notice, this list of conditions and the following disclaimer. 11480565d5SRuslan Ermilov.\" 2. Redistributions in binary form must reproduce the above copyright 12480565d5SRuslan Ermilov.\" notice, this list of conditions and the following disclaimer in the 13480565d5SRuslan Ermilov.\" documentation and/or other materials provided with the distribution. 14480565d5SRuslan Ermilov.\" 3. All advertising materials mentioning features or use of this software 15480565d5SRuslan Ermilov.\" must display the following acknowledgement: 16480565d5SRuslan Ermilov.\" This product includes software developed by Niels Provos. 17480565d5SRuslan Ermilov.\" 4. The name of the author may not be used to endorse or promote products 18480565d5SRuslan Ermilov.\" derived from this software without specific prior written permission. 19480565d5SRuslan Ermilov.\" 20480565d5SRuslan Ermilov.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21480565d5SRuslan Ermilov.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22480565d5SRuslan Ermilov.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23480565d5SRuslan Ermilov.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24480565d5SRuslan Ermilov.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25480565d5SRuslan Ermilov.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26480565d5SRuslan Ermilov.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27480565d5SRuslan Ermilov.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28480565d5SRuslan Ermilov.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29480565d5SRuslan Ermilov.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30480565d5SRuslan Ermilov.\" 31480565d5SRuslan Ermilov.\" $FreeBSD$ 32480565d5SRuslan Ermilov.\" 33*9dbae282SGleb Smirnoff.Dd November 4, 2013 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 , 5687f5f0ecSDag-Erling Smørgrav.Nm RB_GENERATE , 57d72cd779SJason Evans.Nm RB_GENERATE_STATIC , 5887f5f0ecSDag-Erling Smørgrav.Nm RB_ENTRY , 5987f5f0ecSDag-Erling Smørgrav.Nm RB_HEAD , 6087f5f0ecSDag-Erling Smørgrav.Nm RB_INITIALIZER , 6187f5f0ecSDag-Erling Smørgrav.Nm RB_ROOT , 6287f5f0ecSDag-Erling Smørgrav.Nm RB_EMPTY , 6387f5f0ecSDag-Erling Smørgrav.Nm RB_NEXT , 648e4fd0a1SJason Evans.Nm RB_PREV , 6587f5f0ecSDag-Erling Smørgrav.Nm RB_MIN , 6687f5f0ecSDag-Erling Smørgrav.Nm RB_MAX , 6787f5f0ecSDag-Erling Smørgrav.Nm RB_FIND , 6806115e08SJason Evans.Nm RB_NFIND , 6987f5f0ecSDag-Erling Smørgrav.Nm RB_LEFT , 7087f5f0ecSDag-Erling Smørgrav.Nm RB_RIGHT , 7187f5f0ecSDag-Erling Smørgrav.Nm RB_PARENT , 7287f5f0ecSDag-Erling Smørgrav.Nm RB_FOREACH , 73*9dbae282SGleb Smirnoff.Nm RB_FOREACH_SAFE , 748e4fd0a1SJason Evans.Nm RB_FOREACH_REVERSE , 75*9dbae282SGleb Smirnoff.Nm RB_FOREACH_REVERSE_SAFE , 7687f5f0ecSDag-Erling Smørgrav.Nm RB_INIT , 7787f5f0ecSDag-Erling Smørgrav.Nm RB_INSERT , 7887f5f0ecSDag-Erling Smørgrav.Nm RB_REMOVE 7987f5f0ecSDag-Erling Smørgrav.Nd "implementations of splay and red-black trees" 8087f5f0ecSDag-Erling Smørgrav.Sh SYNOPSIS 81480565d5SRuslan Ermilov.In sys/tree.h 82480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP 83480565d5SRuslan Ermilov.Fn SPLAY_GENERATE NAME TYPE FIELD CMP 84480565d5SRuslan Ermilov.Fn SPLAY_ENTRY TYPE 85480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE 8687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 8787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head" 8887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT "SPLAY_HEAD *head" 89480565d5SRuslan Ermilov.Ft bool 9087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY "SPLAY_HEAD *head" 9187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 92480565d5SRuslan Ermilov.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm" 9387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 94480565d5SRuslan Ermilov.Fn SPLAY_MIN NAME "SPLAY_HEAD *head" 9587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 96480565d5SRuslan Ermilov.Fn SPLAY_MAX NAME "SPLAY_HEAD *head" 9787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 98480565d5SRuslan Ermilov.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm" 9987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 10087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME" 10187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 10287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" 103480565d5SRuslan Ermilov.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head" 10487f5f0ecSDag-Erling Smørgrav.Ft void 10587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT "SPLAY_HEAD *head" 10687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 107480565d5SRuslan Ermilov.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm" 10887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 109480565d5SRuslan Ermilov.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm" 110480565d5SRuslan Ermilov.Fn RB_PROTOTYPE NAME TYPE FIELD CMP 111d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP 112480565d5SRuslan Ermilov.Fn RB_GENERATE NAME TYPE FIELD CMP 113d72cd779SJason Evans.Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP 114480565d5SRuslan Ermilov.Fn RB_ENTRY TYPE 115480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE 11687f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER "RB_HEAD *head" 11787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 11887f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT "RB_HEAD *head" 11987f5f0ecSDag-Erling Smørgrav.Ft "bool" 12087f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY "RB_HEAD *head" 12187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 122480565d5SRuslan Ermilov.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm" 12387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 1248e4fd0a1SJason Evans.Fn RB_PREV NAME "RB_HEAD *head" "struct TYPE *elm" 1258e4fd0a1SJason Evans.Ft "struct TYPE *" 126480565d5SRuslan Ermilov.Fn RB_MIN NAME "RB_HEAD *head" 12787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 128480565d5SRuslan Ermilov.Fn RB_MAX NAME "RB_HEAD *head" 12987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 130480565d5SRuslan Ermilov.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm" 13187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 13206115e08SJason Evans.Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm" 13306115e08SJason Evans.Ft "struct TYPE *" 13487f5f0ecSDag-Erling Smørgrav.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" 13587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 13687f5f0ecSDag-Erling Smørgrav.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" 13787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 13887f5f0ecSDag-Erling Smørgrav.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" 139480565d5SRuslan Ermilov.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head" 140*9dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 1418e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head" 142*9dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 14387f5f0ecSDag-Erling Smørgrav.Ft void 14487f5f0ecSDag-Erling Smørgrav.Fn RB_INIT "RB_HEAD *head" 14587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 146480565d5SRuslan Ermilov.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm" 14787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 148480565d5SRuslan Ermilov.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm" 14987f5f0ecSDag-Erling Smørgrav.Sh DESCRIPTION 150480565d5SRuslan ErmilovThese macros define data structures for different types of trees: 15187f5f0ecSDag-Erling Smørgravsplay trees and red-black trees. 15287f5f0ecSDag-Erling Smørgrav.Pp 15387f5f0ecSDag-Erling SmørgravIn the macro definitions, 15487f5f0ecSDag-Erling Smørgrav.Fa TYPE 15587f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must contain a field of type 156480565d5SRuslan Ermilov.Vt SPLAY_ENTRY , 15787f5f0ecSDag-Erling Smørgravor 158480565d5SRuslan Ermilov.Vt RB_ENTRY , 15987f5f0ecSDag-Erling Smørgravnamed 16087f5f0ecSDag-Erling Smørgrav.Fa ENTRYNAME . 16187f5f0ecSDag-Erling SmørgravThe argument 16287f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 16387f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must be declared 16487f5f0ecSDag-Erling Smørgravusing the macros 16587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD , 16687f5f0ecSDag-Erling Smørgravor 16787f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD . 16887f5f0ecSDag-Erling SmørgravThe argument 16987f5f0ecSDag-Erling Smørgrav.Fa NAME 17087f5f0ecSDag-Erling Smørgravhas to be a unique name prefix for every tree that is defined. 17187f5f0ecSDag-Erling Smørgrav.Pp 172d72cd779SJason EvansThe function prototypes are declared with 173480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE , 174d72cd779SJason Evans.Fn RB_PROTOTYPE , 17587f5f0ecSDag-Erling Smørgravor 176d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC . 177d72cd779SJason EvansThe function bodies are generated with 178480565d5SRuslan Ermilov.Fn SPLAY_GENERATE , 179d72cd779SJason Evans.Fn RB_GENERATE , 18087f5f0ecSDag-Erling Smørgravor 181d72cd779SJason Evans.Fn RB_GENERATE_STATIC . 18287f5f0ecSDag-Erling SmørgravSee the examples below for further explanation of how these macros are used. 18387f5f0ecSDag-Erling Smørgrav.Sh SPLAY TREES 184480565d5SRuslan ErmilovA splay tree is a self-organizing data structure. 185480565d5SRuslan ErmilovEvery operation on the tree causes a splay to happen. 186480565d5SRuslan ErmilovThe splay moves the requested 18787f5f0ecSDag-Erling Smørgravnode to the root of the tree and partly rebalances it. 18887f5f0ecSDag-Erling Smørgrav.Pp 18987f5f0ecSDag-Erling SmørgravThis has the benefit that request locality causes faster lookups as 190480565d5SRuslan Ermilovthe requested nodes move to the top of the tree. 191480565d5SRuslan ErmilovOn the other hand, every lookup causes memory writes. 19287f5f0ecSDag-Erling Smørgrav.Pp 193480565d5SRuslan ErmilovThe Balance Theorem bounds the total access time for 194480565d5SRuslan Ermilov.Ar m 195480565d5SRuslan Ermilovoperations and 196480565d5SRuslan Ermilov.Ar n 197480565d5SRuslan Ermilovinserts on an initially empty tree as 198480565d5SRuslan Ermilov.Fn O "\*[lp]m + n\*[rp]lg n" . 199480565d5SRuslan ErmilovThe 200480565d5SRuslan Ermilovamortized cost for a sequence of 201480565d5SRuslan Ermilov.Ar m 202480565d5SRuslan Ermilovaccesses to a splay tree is 203480565d5SRuslan Ermilov.Fn O "lg n" . 20487f5f0ecSDag-Erling Smørgrav.Pp 20587f5f0ecSDag-Erling SmørgravA splay tree is headed by a structure defined by the 20687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD 20787f5f0ecSDag-Erling Smørgravmacro. 20887f5f0ecSDag-Erling SmørgravA 20987f5f0ecSDag-Erling Smørgravstructure is declared as follows: 210480565d5SRuslan Ermilov.Bd -ragged -offset indent 211480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE 212480565d5SRuslan Ermilov.Va head ; 21387f5f0ecSDag-Erling Smørgrav.Ed 21487f5f0ecSDag-Erling Smørgrav.Pp 21587f5f0ecSDag-Erling Smørgravwhere 21687f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 21787f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct 21887f5f0ecSDag-Erling Smørgrav.Fa TYPE 21987f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree. 22087f5f0ecSDag-Erling Smørgrav.Pp 22187f5f0ecSDag-Erling SmørgravThe 22287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY 22387f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree. 22487f5f0ecSDag-Erling Smørgrav.Pp 22587f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure, 22687f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the 22787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE 22887f5f0ecSDag-Erling Smørgravmacro, 22987f5f0ecSDag-Erling Smørgravwhere 23087f5f0ecSDag-Erling Smørgrav.Fa NAME 23187f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree. 23287f5f0ecSDag-Erling SmørgravThe 23387f5f0ecSDag-Erling Smørgrav.Fa TYPE 23487f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed 23587f5f0ecSDag-Erling Smørgravby the tree. 23687f5f0ecSDag-Erling SmørgravThe 23787f5f0ecSDag-Erling Smørgrav.Fa FIELD 23887f5f0ecSDag-Erling Smørgravargument is the name of the element defined by 23987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY . 24087f5f0ecSDag-Erling Smørgrav.Pp 24187f5f0ecSDag-Erling SmørgravThe function bodies are generated with the 24287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_GENERATE 243480565d5SRuslan Ermilovmacro. 244480565d5SRuslan ErmilovIt takes the same arguments as the 24587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE 24687f5f0ecSDag-Erling Smørgravmacro, but should be used only once. 24787f5f0ecSDag-Erling Smørgrav.Pp 24887f5f0ecSDag-Erling SmørgravFinally, 24987f5f0ecSDag-Erling Smørgravthe 25087f5f0ecSDag-Erling Smørgrav.Fa CMP 251480565d5SRuslan Ermilovargument is the name of a function used to compare tree nodes 252480565d5SRuslan Ermilovwith each other. 253480565d5SRuslan ErmilovThe function takes two arguments of type 254480565d5SRuslan Ermilov.Vt "struct TYPE *" . 25587f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a 256480565d5SRuslan Ermilovvalue smaller than zero. 257480565d5SRuslan ErmilovIf they are equal, the function returns zero. 258480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero. 259480565d5SRuslan ErmilovThe compare 26087f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements. 26187f5f0ecSDag-Erling Smørgrav.Pp 26287f5f0ecSDag-Erling SmørgravThe 26387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT 26487f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by 26587f5f0ecSDag-Erling Smørgrav.Fa head . 26687f5f0ecSDag-Erling Smørgrav.Pp 26787f5f0ecSDag-Erling SmørgravThe splay tree can also be initialized statically by using the 26887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER 26987f5f0ecSDag-Erling Smørgravmacro like this: 270480565d5SRuslan Ermilov.Bd -ragged -offset indent 271480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE 272480565d5SRuslan Ermilov.Va head 273480565d5SRuslan Ermilov= 274480565d5SRuslan Ermilov.Fn SPLAY_INITIALIZER &head ; 27587f5f0ecSDag-Erling Smørgrav.Ed 27687f5f0ecSDag-Erling Smørgrav.Pp 27787f5f0ecSDag-Erling SmørgravThe 27887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT 27987f5f0ecSDag-Erling Smørgravmacro inserts the new element 28087f5f0ecSDag-Erling Smørgrav.Fa elm 28187f5f0ecSDag-Erling Smørgravinto the tree. 28287f5f0ecSDag-Erling Smørgrav.Pp 28387f5f0ecSDag-Erling SmørgravThe 28487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE 28587f5f0ecSDag-Erling Smørgravmacro removes the element 28687f5f0ecSDag-Erling Smørgrav.Fa elm 28787f5f0ecSDag-Erling Smørgravfrom the tree pointed by 28887f5f0ecSDag-Erling Smørgrav.Fa head . 28987f5f0ecSDag-Erling Smørgrav.Pp 29087f5f0ecSDag-Erling SmørgravThe 29187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FIND 29287f5f0ecSDag-Erling Smørgravmacro can be used to find a particular element in the tree. 29387f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 29487f5f0ecSDag-Erling Smørgravstruct TYPE find, *res; 29587f5f0ecSDag-Erling Smørgravfind.key = 30; 29687f5f0ecSDag-Erling Smørgravres = SPLAY_FIND(NAME, head, &find); 29787f5f0ecSDag-Erling Smørgrav.Ed 29887f5f0ecSDag-Erling Smørgrav.Pp 29987f5f0ecSDag-Erling SmørgravThe 30087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT , 30187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MIN , 30287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MAX , 30387f5f0ecSDag-Erling Smørgravand 30487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_NEXT 30587f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree: 30687f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 30787f5f0ecSDag-Erling Smørgravfor (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np)) 30887f5f0ecSDag-Erling Smørgrav.Ed 30987f5f0ecSDag-Erling Smørgrav.Pp 31087f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the 31187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FOREACH 31287f5f0ecSDag-Erling Smørgravmacro: 313480565d5SRuslan Ermilov.Bd -ragged -offset indent 314480565d5SRuslan Ermilov.Fn SPLAY_FOREACH np NAME head 31587f5f0ecSDag-Erling Smørgrav.Ed 31687f5f0ecSDag-Erling Smørgrav.Pp 31787f5f0ecSDag-Erling SmørgravThe 31887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY 31987f5f0ecSDag-Erling Smørgravmacro should be used to check whether a splay tree is empty. 32087f5f0ecSDag-Erling Smørgrav.Sh RED-BLACK TREES 32187f5f0ecSDag-Erling SmørgravA red-black tree is a binary search tree with the node color as an 322480565d5SRuslan Ermilovextra attribute. 323480565d5SRuslan ErmilovIt fulfills a set of conditions: 324480565d5SRuslan Ermilov.Bl -enum -offset indent 32587f5f0ecSDag-Erling Smørgrav.It 326480565d5SRuslan ErmilovEvery search path from the root to a leaf consists of the same number of 327480565d5SRuslan Ermilovblack nodes. 32887f5f0ecSDag-Erling Smørgrav.It 329480565d5SRuslan ErmilovEach red node (except for the root) has a black parent. 33087f5f0ecSDag-Erling Smørgrav.It 331480565d5SRuslan ErmilovEach leaf node is black. 33287f5f0ecSDag-Erling Smørgrav.El 33387f5f0ecSDag-Erling Smørgrav.Pp 334480565d5SRuslan ErmilovEvery operation on a red-black tree is bounded as 335480565d5SRuslan Ermilov.Fn O "lg n" . 336480565d5SRuslan ErmilovThe maximum height of a red-black tree is 337480565d5SRuslan Ermilov.Fn 2lg "n + 1" . 33887f5f0ecSDag-Erling Smørgrav.Pp 33987f5f0ecSDag-Erling SmørgravA red-black tree is headed by a structure defined by the 34087f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD 34187f5f0ecSDag-Erling Smørgravmacro. 34287f5f0ecSDag-Erling SmørgravA 34387f5f0ecSDag-Erling Smørgravstructure is declared as follows: 344480565d5SRuslan Ermilov.Bd -ragged -offset indent 345480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE 346480565d5SRuslan Ermilov.Va head ; 34787f5f0ecSDag-Erling Smørgrav.Ed 34887f5f0ecSDag-Erling Smørgrav.Pp 34987f5f0ecSDag-Erling Smørgravwhere 35087f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 35187f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct 35287f5f0ecSDag-Erling Smørgrav.Fa TYPE 35387f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree. 35487f5f0ecSDag-Erling Smørgrav.Pp 35587f5f0ecSDag-Erling SmørgravThe 35687f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY 35787f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree. 35887f5f0ecSDag-Erling Smørgrav.Pp 35987f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure, 36087f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the 36187f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE 362d72cd779SJason Evansor 363d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC 36487f5f0ecSDag-Erling Smørgravmacro, 36587f5f0ecSDag-Erling Smørgravwhere 36687f5f0ecSDag-Erling Smørgrav.Fa NAME 36787f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree. 36887f5f0ecSDag-Erling SmørgravThe 36987f5f0ecSDag-Erling Smørgrav.Fa TYPE 37087f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed 37187f5f0ecSDag-Erling Smørgravby the tree. 37287f5f0ecSDag-Erling SmørgravThe 37387f5f0ecSDag-Erling Smørgrav.Fa FIELD 37487f5f0ecSDag-Erling Smørgravargument is the name of the element defined by 37587f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY . 37687f5f0ecSDag-Erling Smørgrav.Pp 37787f5f0ecSDag-Erling SmørgravThe function bodies are generated with the 37887f5f0ecSDag-Erling Smørgrav.Fn RB_GENERATE 379d72cd779SJason Evansor 380d72cd779SJason Evans.Fn RB_GENERATE_STATIC 381480565d5SRuslan Ermilovmacro. 382d72cd779SJason EvansThese macros take the same arguments as the 38387f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE 384d72cd779SJason Evansand 385d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC 386d72cd779SJason Evansmacros, but should be used only once. 38787f5f0ecSDag-Erling Smørgrav.Pp 38887f5f0ecSDag-Erling SmørgravFinally, 38987f5f0ecSDag-Erling Smørgravthe 39087f5f0ecSDag-Erling Smørgrav.Fa CMP 3919d44cd42SBenno Riceargument is the name of a function used to compare tree nodes 392480565d5SRuslan Ermilovwith each other. 393480565d5SRuslan ErmilovThe function takes two arguments of type 394480565d5SRuslan Ermilov.Vt "struct TYPE *" . 39587f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a 396480565d5SRuslan Ermilovvalue smaller than zero. 397480565d5SRuslan ErmilovIf they are equal, the function returns zero. 398480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero. 399480565d5SRuslan ErmilovThe compare 40087f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements. 40187f5f0ecSDag-Erling Smørgrav.Pp 40287f5f0ecSDag-Erling SmørgravThe 40387f5f0ecSDag-Erling Smørgrav.Fn RB_INIT 40487f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by 40587f5f0ecSDag-Erling Smørgrav.Fa head . 40687f5f0ecSDag-Erling Smørgrav.Pp 4073b96c71fSMike PritchardThe red-black tree can also be initialized statically by using the 40887f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER 40987f5f0ecSDag-Erling Smørgravmacro like this: 410480565d5SRuslan Ermilov.Bd -ragged -offset indent 411480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE 412480565d5SRuslan Ermilov.Va head 413480565d5SRuslan Ermilov= 414480565d5SRuslan Ermilov.Fn RB_INITIALIZER &head ; 41587f5f0ecSDag-Erling Smørgrav.Ed 41687f5f0ecSDag-Erling Smørgrav.Pp 41787f5f0ecSDag-Erling SmørgravThe 41887f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT 41987f5f0ecSDag-Erling Smørgravmacro inserts the new element 42087f5f0ecSDag-Erling Smørgrav.Fa elm 42187f5f0ecSDag-Erling Smørgravinto the tree. 42287f5f0ecSDag-Erling Smørgrav.Pp 42387f5f0ecSDag-Erling SmørgravThe 42487f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE 42587f5f0ecSDag-Erling Smørgravmacro removes the element 42687f5f0ecSDag-Erling Smørgrav.Fa elm 42787f5f0ecSDag-Erling Smørgravfrom the tree pointed by 42887f5f0ecSDag-Erling Smørgrav.Fa head . 42987f5f0ecSDag-Erling Smørgrav.Pp 43087f5f0ecSDag-Erling SmørgravThe 43187f5f0ecSDag-Erling Smørgrav.Fn RB_FIND 43206115e08SJason Evansand 43306115e08SJason Evans.Fn RB_NFIND 43406115e08SJason Evansmacros can be used to find a particular element in the tree. 43587f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 43687f5f0ecSDag-Erling Smørgravstruct TYPE find, *res; 43787f5f0ecSDag-Erling Smørgravfind.key = 30; 43887f5f0ecSDag-Erling Smørgravres = RB_FIND(NAME, head, &find); 43987f5f0ecSDag-Erling Smørgrav.Ed 44087f5f0ecSDag-Erling Smørgrav.Pp 44187f5f0ecSDag-Erling SmørgravThe 44287f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT , 44387f5f0ecSDag-Erling Smørgrav.Fn RB_MIN , 44487f5f0ecSDag-Erling Smørgrav.Fn RB_MAX , 4458e4fd0a1SJason Evans.Fn RB_NEXT , 44687f5f0ecSDag-Erling Smørgravand 4478e4fd0a1SJason Evans.Fn RB_PREV 44887f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree: 449480565d5SRuslan Ermilov.Pp 450480565d5SRuslan Ermilov.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))" 45187f5f0ecSDag-Erling Smørgrav.Pp 45287f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the 45387f5f0ecSDag-Erling Smørgrav.Fn RB_FOREACH 4548e4fd0a1SJason Evansor 4558e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE 45687f5f0ecSDag-Erling Smørgravmacro: 457480565d5SRuslan Ermilov.Bd -ragged -offset indent 458480565d5SRuslan Ermilov.Fn RB_FOREACH np NAME head 45987f5f0ecSDag-Erling Smørgrav.Ed 46087f5f0ecSDag-Erling Smørgrav.Pp 461*9dbae282SGleb SmirnoffThe macros 462*9dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE 463*9dbae282SGleb Smirnoffand 464*9dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE 465*9dbae282SGleb Smirnofftraverse the tree referenced by head 466*9dbae282SGleb Smirnoffin a forward or reverse direction respectively, 467*9dbae282SGleb Smirnoffassigning each element in turn to np. 468*9dbae282SGleb SmirnoffHowever, unlike their unsafe counterparts, 469*9dbae282SGleb Smirnoffthey permit both the removal of np 470*9dbae282SGleb Smirnoffas well as freeing it from within the loop safely 471*9dbae282SGleb Smirnoffwithout interfering with the traversal. 472*9dbae282SGleb Smirnoff.Pp 47387f5f0ecSDag-Erling SmørgravThe 47487f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY 475309e4b9bSDag-Erling Smørgravmacro should be used to check whether a red-black tree is empty. 47687f5f0ecSDag-Erling Smørgrav.Sh NOTES 47787f5f0ecSDag-Erling SmørgravTrying to free a tree in the following way is a common error: 47887f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 47987f5f0ecSDag-Erling SmørgravSPLAY_FOREACH(var, NAME, head) { 48087f5f0ecSDag-Erling Smørgrav SPLAY_REMOVE(NAME, head, var); 48187f5f0ecSDag-Erling Smørgrav free(var); 48287f5f0ecSDag-Erling Smørgrav} 48387f5f0ecSDag-Erling Smørgravfree(head); 48487f5f0ecSDag-Erling Smørgrav.Ed 48587f5f0ecSDag-Erling Smørgrav.Pp 48687f5f0ecSDag-Erling SmørgravSince 48787f5f0ecSDag-Erling Smørgrav.Va var 488480565d5SRuslan Ermilovis freed, the 48987f5f0ecSDag-Erling Smørgrav.Fn FOREACH 49087f5f0ecSDag-Erling Smørgravmacro refers to a pointer that may have been reallocated already. 49187f5f0ecSDag-Erling SmørgravProper code needs a second variable. 49287f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 49387f5f0ecSDag-Erling Smørgravfor (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) { 49487f5f0ecSDag-Erling Smørgrav nxt = SPLAY_NEXT(NAME, head, var); 49587f5f0ecSDag-Erling Smørgrav SPLAY_REMOVE(NAME, head, var); 49687f5f0ecSDag-Erling Smørgrav free(var); 49787f5f0ecSDag-Erling Smørgrav} 49887f5f0ecSDag-Erling Smørgrav.Ed 49987f5f0ecSDag-Erling Smørgrav.Pp 50087f5f0ecSDag-Erling SmørgravBoth 50187f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT 50287f5f0ecSDag-Erling Smørgravand 50387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT 50487f5f0ecSDag-Erling Smørgravreturn 505480565d5SRuslan Ermilov.Dv NULL 50687f5f0ecSDag-Erling Smørgravif the element was inserted in the tree successfully, otherwise they 50787f5f0ecSDag-Erling Smørgravreturn a pointer to the element with the colliding key. 50887f5f0ecSDag-Erling Smørgrav.Pp 50987f5f0ecSDag-Erling SmørgravAccordingly, 51087f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE 51187f5f0ecSDag-Erling Smørgravand 51287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE 51387f5f0ecSDag-Erling Smørgravreturn the pointer to the removed element otherwise they return 514480565d5SRuslan Ermilov.Dv NULL 51587f5f0ecSDag-Erling Smørgravto indicate an error. 516b9ec8f3bSSimon L. B. Nielsen.Sh SEE ALSO 517b9ec8f3bSSimon L. B. Nielsen.Xr queue 3 51887f5f0ecSDag-Erling Smørgrav.Sh AUTHORS 519480565d5SRuslan ErmilovThe author of the tree macros is 520480565d5SRuslan Ermilov.An Niels Provos . 521