187f5f0ecSDag-Erling Smørgrav.\" $OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $ 2480565d5SRuslan Ermilov.\" 3480565d5SRuslan Ermilov.\" Copyright 2002 Niels Provos <provos@citi.umich.edu> 4480565d5SRuslan Ermilov.\" All rights reserved. 5480565d5SRuslan Ermilov.\" 6480565d5SRuslan Ermilov.\" Redistribution and use in source and binary forms, with or without 7480565d5SRuslan Ermilov.\" modification, are permitted provided that the following conditions 8480565d5SRuslan Ermilov.\" are met: 9480565d5SRuslan Ermilov.\" 1. Redistributions of source code must retain the above copyright 10480565d5SRuslan Ermilov.\" notice, this list of conditions and the following disclaimer. 11480565d5SRuslan Ermilov.\" 2. Redistributions in binary form must reproduce the above copyright 12480565d5SRuslan Ermilov.\" notice, this list of conditions and the following disclaimer in the 13480565d5SRuslan Ermilov.\" documentation and/or other materials provided with the distribution. 14480565d5SRuslan Ermilov.\" 3. All advertising materials mentioning features or use of this software 15480565d5SRuslan Ermilov.\" must display the following acknowledgement: 16480565d5SRuslan Ermilov.\" This product includes software developed by Niels Provos. 17480565d5SRuslan Ermilov.\" 4. The name of the author may not be used to endorse or promote products 18480565d5SRuslan Ermilov.\" derived from this software without specific prior written permission. 19480565d5SRuslan Ermilov.\" 20480565d5SRuslan Ermilov.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21480565d5SRuslan Ermilov.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22480565d5SRuslan Ermilov.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23480565d5SRuslan Ermilov.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24480565d5SRuslan Ermilov.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25480565d5SRuslan Ermilov.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26480565d5SRuslan Ermilov.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27480565d5SRuslan Ermilov.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28480565d5SRuslan Ermilov.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29480565d5SRuslan Ermilov.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30480565d5SRuslan Ermilov.\" 31480565d5SRuslan Ermilov.\" $FreeBSD$ 32480565d5SRuslan Ermilov.\" 3387f5f0ecSDag-Erling Smørgrav.Dd February 24, 2002 3487f5f0ecSDag-Erling Smørgrav.Dt TREE 3 3587f5f0ecSDag-Erling Smørgrav.Os 3687f5f0ecSDag-Erling Smørgrav.Sh NAME 3787f5f0ecSDag-Erling Smørgrav.Nm SPLAY_PROTOTYPE , 3887f5f0ecSDag-Erling Smørgrav.Nm SPLAY_GENERATE , 3987f5f0ecSDag-Erling Smørgrav.Nm SPLAY_ENTRY , 4087f5f0ecSDag-Erling Smørgrav.Nm SPLAY_HEAD , 4187f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INITIALIZER , 4287f5f0ecSDag-Erling Smørgrav.Nm SPLAY_ROOT , 4387f5f0ecSDag-Erling Smørgrav.Nm SPLAY_EMPTY , 4487f5f0ecSDag-Erling Smørgrav.Nm SPLAY_NEXT , 4587f5f0ecSDag-Erling Smørgrav.Nm SPLAY_MIN , 4687f5f0ecSDag-Erling Smørgrav.Nm SPLAY_MAX , 4787f5f0ecSDag-Erling Smørgrav.Nm SPLAY_FIND , 4887f5f0ecSDag-Erling Smørgrav.Nm SPLAY_LEFT , 4987f5f0ecSDag-Erling Smørgrav.Nm SPLAY_RIGHT , 5087f5f0ecSDag-Erling Smørgrav.Nm SPLAY_FOREACH , 5187f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INIT , 5287f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INSERT , 5387f5f0ecSDag-Erling Smørgrav.Nm SPLAY_REMOVE , 5487f5f0ecSDag-Erling Smørgrav.Nm RB_PROTOTYPE , 5587f5f0ecSDag-Erling Smørgrav.Nm RB_GENERATE , 5687f5f0ecSDag-Erling Smørgrav.Nm RB_ENTRY , 5787f5f0ecSDag-Erling Smørgrav.Nm RB_HEAD , 5887f5f0ecSDag-Erling Smørgrav.Nm RB_INITIALIZER , 5987f5f0ecSDag-Erling Smørgrav.Nm RB_ROOT , 6087f5f0ecSDag-Erling Smørgrav.Nm RB_EMPTY , 6187f5f0ecSDag-Erling Smørgrav.Nm RB_NEXT , 6287f5f0ecSDag-Erling Smørgrav.Nm RB_MIN , 6387f5f0ecSDag-Erling Smørgrav.Nm RB_MAX , 6487f5f0ecSDag-Erling Smørgrav.Nm RB_FIND , 6506115e08SJason Evans.Nm RB_NFIND , 6687f5f0ecSDag-Erling Smørgrav.Nm RB_LEFT , 6787f5f0ecSDag-Erling Smørgrav.Nm RB_RIGHT , 6887f5f0ecSDag-Erling Smørgrav.Nm RB_PARENT , 6987f5f0ecSDag-Erling Smørgrav.Nm RB_FOREACH , 7087f5f0ecSDag-Erling Smørgrav.Nm RB_INIT , 7187f5f0ecSDag-Erling Smørgrav.Nm RB_INSERT , 7287f5f0ecSDag-Erling Smørgrav.Nm RB_REMOVE 7387f5f0ecSDag-Erling Smørgrav.Nd "implementations of splay and red-black trees" 7487f5f0ecSDag-Erling Smørgrav.Sh SYNOPSIS 75480565d5SRuslan Ermilov.In sys/tree.h 76480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP 77480565d5SRuslan Ermilov.Fn SPLAY_GENERATE NAME TYPE FIELD CMP 78480565d5SRuslan Ermilov.Fn SPLAY_ENTRY TYPE 79480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE 8087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 8187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head" 8287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT "SPLAY_HEAD *head" 83480565d5SRuslan Ermilov.Ft bool 8487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY "SPLAY_HEAD *head" 8587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 86480565d5SRuslan Ermilov.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm" 8787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 88480565d5SRuslan Ermilov.Fn SPLAY_MIN NAME "SPLAY_HEAD *head" 8987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 90480565d5SRuslan Ermilov.Fn SPLAY_MAX NAME "SPLAY_HEAD *head" 9187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 92480565d5SRuslan Ermilov.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm" 9387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 9487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME" 9587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 9687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" 97480565d5SRuslan Ermilov.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head" 9887f5f0ecSDag-Erling Smørgrav.Ft void 9987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT "SPLAY_HEAD *head" 10087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 101480565d5SRuslan Ermilov.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm" 10287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 103480565d5SRuslan Ermilov.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm" 104480565d5SRuslan Ermilov.Fn RB_PROTOTYPE NAME TYPE FIELD CMP 105480565d5SRuslan Ermilov.Fn RB_GENERATE NAME TYPE FIELD CMP 106480565d5SRuslan Ermilov.Fn RB_ENTRY TYPE 107480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE 10887f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER "RB_HEAD *head" 10987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 11087f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT "RB_HEAD *head" 11187f5f0ecSDag-Erling Smørgrav.Ft "bool" 11287f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY "RB_HEAD *head" 11387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 114480565d5SRuslan Ermilov.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm" 11587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 116480565d5SRuslan Ermilov.Fn RB_MIN NAME "RB_HEAD *head" 11787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 118480565d5SRuslan Ermilov.Fn RB_MAX NAME "RB_HEAD *head" 11987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 120480565d5SRuslan Ermilov.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm" 12187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 12206115e08SJason Evans.Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm" 12306115e08SJason Evans.Ft "struct TYPE *" 12487f5f0ecSDag-Erling Smørgrav.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" 12587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 12687f5f0ecSDag-Erling Smørgrav.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" 12787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 12887f5f0ecSDag-Erling Smørgrav.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" 129480565d5SRuslan Ermilov.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head" 13087f5f0ecSDag-Erling Smørgrav.Ft void 13187f5f0ecSDag-Erling Smørgrav.Fn RB_INIT "RB_HEAD *head" 13287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 133480565d5SRuslan Ermilov.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm" 13487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 135480565d5SRuslan Ermilov.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm" 13687f5f0ecSDag-Erling Smørgrav.Sh DESCRIPTION 137480565d5SRuslan ErmilovThese macros define data structures for different types of trees: 13887f5f0ecSDag-Erling Smørgravsplay trees and red-black trees. 13987f5f0ecSDag-Erling Smørgrav.Pp 14087f5f0ecSDag-Erling SmørgravIn the macro definitions, 14187f5f0ecSDag-Erling Smørgrav.Fa TYPE 14287f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must contain a field of type 143480565d5SRuslan Ermilov.Vt SPLAY_ENTRY , 14487f5f0ecSDag-Erling Smørgravor 145480565d5SRuslan Ermilov.Vt RB_ENTRY , 14687f5f0ecSDag-Erling Smørgravnamed 14787f5f0ecSDag-Erling Smørgrav.Fa ENTRYNAME . 14887f5f0ecSDag-Erling SmørgravThe argument 14987f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 15087f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must be declared 15187f5f0ecSDag-Erling Smørgravusing the macros 15287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD , 15387f5f0ecSDag-Erling Smørgravor 15487f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD . 15587f5f0ecSDag-Erling SmørgravThe argument 15687f5f0ecSDag-Erling Smørgrav.Fa NAME 15787f5f0ecSDag-Erling Smørgravhas to be a unique name prefix for every tree that is defined. 15887f5f0ecSDag-Erling Smørgrav.Pp 15987f5f0ecSDag-Erling SmørgravThe function prototypes are declared with either 160480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE , 16187f5f0ecSDag-Erling Smørgravor 162480565d5SRuslan Ermilov.Fn RB_PROTOTYPE . 16387f5f0ecSDag-Erling SmørgravThe function bodies are generated with either 164480565d5SRuslan Ermilov.Fn SPLAY_GENERATE , 16587f5f0ecSDag-Erling Smørgravor 166480565d5SRuslan Ermilov.Fn RB_GENERATE . 16787f5f0ecSDag-Erling SmørgravSee the examples below for further explanation of how these macros are used. 16887f5f0ecSDag-Erling Smørgrav.Sh SPLAY TREES 169480565d5SRuslan ErmilovA splay tree is a self-organizing data structure. 170480565d5SRuslan ErmilovEvery operation on the tree causes a splay to happen. 171480565d5SRuslan ErmilovThe splay moves the requested 17287f5f0ecSDag-Erling Smørgravnode to the root of the tree and partly rebalances it. 17387f5f0ecSDag-Erling Smørgrav.Pp 17487f5f0ecSDag-Erling SmørgravThis has the benefit that request locality causes faster lookups as 175480565d5SRuslan Ermilovthe requested nodes move to the top of the tree. 176480565d5SRuslan ErmilovOn the other hand, every lookup causes memory writes. 17787f5f0ecSDag-Erling Smørgrav.Pp 178480565d5SRuslan ErmilovThe Balance Theorem bounds the total access time for 179480565d5SRuslan Ermilov.Ar m 180480565d5SRuslan Ermilovoperations and 181480565d5SRuslan Ermilov.Ar n 182480565d5SRuslan Ermilovinserts on an initially empty tree as 183480565d5SRuslan Ermilov.Fn O "\*[lp]m + n\*[rp]lg n" . 184480565d5SRuslan ErmilovThe 185480565d5SRuslan Ermilovamortized cost for a sequence of 186480565d5SRuslan Ermilov.Ar m 187480565d5SRuslan Ermilovaccesses to a splay tree is 188480565d5SRuslan Ermilov.Fn O "lg n" . 18987f5f0ecSDag-Erling Smørgrav.Pp 19087f5f0ecSDag-Erling SmørgravA splay tree is headed by a structure defined by the 19187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD 19287f5f0ecSDag-Erling Smørgravmacro. 19387f5f0ecSDag-Erling SmørgravA 19487f5f0ecSDag-Erling Smørgravstructure is declared as follows: 195480565d5SRuslan Ermilov.Bd -ragged -offset indent 196480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE 197480565d5SRuslan Ermilov.Va head ; 19887f5f0ecSDag-Erling Smørgrav.Ed 19987f5f0ecSDag-Erling Smørgrav.Pp 20087f5f0ecSDag-Erling Smørgravwhere 20187f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 20287f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct 20387f5f0ecSDag-Erling Smørgrav.Fa TYPE 20487f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree. 20587f5f0ecSDag-Erling Smørgrav.Pp 20687f5f0ecSDag-Erling SmørgravThe 20787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY 20887f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree. 20987f5f0ecSDag-Erling Smørgrav.Pp 21087f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure, 21187f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the 21287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE 21387f5f0ecSDag-Erling Smørgravmacro, 21487f5f0ecSDag-Erling Smørgravwhere 21587f5f0ecSDag-Erling Smørgrav.Fa NAME 21687f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree. 21787f5f0ecSDag-Erling SmørgravThe 21887f5f0ecSDag-Erling Smørgrav.Fa TYPE 21987f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed 22087f5f0ecSDag-Erling Smørgravby the tree. 22187f5f0ecSDag-Erling SmørgravThe 22287f5f0ecSDag-Erling Smørgrav.Fa FIELD 22387f5f0ecSDag-Erling Smørgravargument is the name of the element defined by 22487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY . 22587f5f0ecSDag-Erling Smørgrav.Pp 22687f5f0ecSDag-Erling SmørgravThe function bodies are generated with the 22787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_GENERATE 228480565d5SRuslan Ermilovmacro. 229480565d5SRuslan ErmilovIt takes the same arguments as the 23087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE 23187f5f0ecSDag-Erling Smørgravmacro, but should be used only once. 23287f5f0ecSDag-Erling Smørgrav.Pp 23387f5f0ecSDag-Erling SmørgravFinally, 23487f5f0ecSDag-Erling Smørgravthe 23587f5f0ecSDag-Erling Smørgrav.Fa CMP 236480565d5SRuslan Ermilovargument is the name of a function used to compare tree nodes 237480565d5SRuslan Ermilovwith each other. 238480565d5SRuslan ErmilovThe function takes two arguments of type 239480565d5SRuslan Ermilov.Vt "struct TYPE *" . 24087f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a 241480565d5SRuslan Ermilovvalue smaller than zero. 242480565d5SRuslan ErmilovIf they are equal, the function returns zero. 243480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero. 244480565d5SRuslan ErmilovThe compare 24587f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements. 24687f5f0ecSDag-Erling Smørgrav.Pp 24787f5f0ecSDag-Erling SmørgravThe 24887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT 24987f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by 25087f5f0ecSDag-Erling Smørgrav.Fa head . 25187f5f0ecSDag-Erling Smørgrav.Pp 25287f5f0ecSDag-Erling SmørgravThe splay tree can also be initialized statically by using the 25387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER 25487f5f0ecSDag-Erling Smørgravmacro like this: 255480565d5SRuslan Ermilov.Bd -ragged -offset indent 256480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE 257480565d5SRuslan Ermilov.Va head 258480565d5SRuslan Ermilov= 259480565d5SRuslan Ermilov.Fn SPLAY_INITIALIZER &head ; 26087f5f0ecSDag-Erling Smørgrav.Ed 26187f5f0ecSDag-Erling Smørgrav.Pp 26287f5f0ecSDag-Erling SmørgravThe 26387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT 26487f5f0ecSDag-Erling Smørgravmacro inserts the new element 26587f5f0ecSDag-Erling Smørgrav.Fa elm 26687f5f0ecSDag-Erling Smørgravinto the tree. 26787f5f0ecSDag-Erling Smørgrav.Pp 26887f5f0ecSDag-Erling SmørgravThe 26987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE 27087f5f0ecSDag-Erling Smørgravmacro removes the element 27187f5f0ecSDag-Erling Smørgrav.Fa elm 27287f5f0ecSDag-Erling Smørgravfrom the tree pointed by 27387f5f0ecSDag-Erling Smørgrav.Fa head . 27487f5f0ecSDag-Erling Smørgrav.Pp 27587f5f0ecSDag-Erling SmørgravThe 27687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FIND 27787f5f0ecSDag-Erling Smørgravmacro can be used to find a particular element in the tree. 27887f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 27987f5f0ecSDag-Erling Smørgravstruct TYPE find, *res; 28087f5f0ecSDag-Erling Smørgravfind.key = 30; 28187f5f0ecSDag-Erling Smørgravres = SPLAY_FIND(NAME, head, &find); 28287f5f0ecSDag-Erling Smørgrav.Ed 28387f5f0ecSDag-Erling Smørgrav.Pp 28487f5f0ecSDag-Erling SmørgravThe 28587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT , 28687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MIN , 28787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MAX , 28887f5f0ecSDag-Erling Smørgravand 28987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_NEXT 29087f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree: 29187f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 29287f5f0ecSDag-Erling Smørgravfor (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np)) 29387f5f0ecSDag-Erling Smørgrav.Ed 29487f5f0ecSDag-Erling Smørgrav.Pp 29587f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the 29687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FOREACH 29787f5f0ecSDag-Erling Smørgravmacro: 298480565d5SRuslan Ermilov.Bd -ragged -offset indent 299480565d5SRuslan Ermilov.Fn SPLAY_FOREACH np NAME head 30087f5f0ecSDag-Erling Smørgrav.Ed 30187f5f0ecSDag-Erling Smørgrav.Pp 30287f5f0ecSDag-Erling SmørgravThe 30387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY 30487f5f0ecSDag-Erling Smørgravmacro should be used to check whether a splay tree is empty. 30587f5f0ecSDag-Erling Smørgrav.Sh RED-BLACK TREES 30687f5f0ecSDag-Erling SmørgravA red-black tree is a binary search tree with the node color as an 307480565d5SRuslan Ermilovextra attribute. 308480565d5SRuslan ErmilovIt fulfills a set of conditions: 309480565d5SRuslan Ermilov.Bl -enum -offset indent 31087f5f0ecSDag-Erling Smørgrav.It 311480565d5SRuslan ErmilovEvery search path from the root to a leaf consists of the same number of 312480565d5SRuslan Ermilovblack nodes. 31387f5f0ecSDag-Erling Smørgrav.It 314480565d5SRuslan ErmilovEach red node (except for the root) has a black parent. 31587f5f0ecSDag-Erling Smørgrav.It 316480565d5SRuslan ErmilovEach leaf node is black. 31787f5f0ecSDag-Erling Smørgrav.El 31887f5f0ecSDag-Erling Smørgrav.Pp 319480565d5SRuslan ErmilovEvery operation on a red-black tree is bounded as 320480565d5SRuslan Ermilov.Fn O "lg n" . 321480565d5SRuslan ErmilovThe maximum height of a red-black tree is 322480565d5SRuslan Ermilov.Fn 2lg "n + 1" . 32387f5f0ecSDag-Erling Smørgrav.Pp 32487f5f0ecSDag-Erling SmørgravA red-black tree is headed by a structure defined by the 32587f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD 32687f5f0ecSDag-Erling Smørgravmacro. 32787f5f0ecSDag-Erling SmørgravA 32887f5f0ecSDag-Erling Smørgravstructure is declared as follows: 329480565d5SRuslan Ermilov.Bd -ragged -offset indent 330480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE 331480565d5SRuslan Ermilov.Va head ; 33287f5f0ecSDag-Erling Smørgrav.Ed 33387f5f0ecSDag-Erling Smørgrav.Pp 33487f5f0ecSDag-Erling Smørgravwhere 33587f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 33687f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct 33787f5f0ecSDag-Erling Smørgrav.Fa TYPE 33887f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree. 33987f5f0ecSDag-Erling Smørgrav.Pp 34087f5f0ecSDag-Erling SmørgravThe 34187f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY 34287f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree. 34387f5f0ecSDag-Erling Smørgrav.Pp 34487f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure, 34587f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the 34687f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE 34787f5f0ecSDag-Erling Smørgravmacro, 34887f5f0ecSDag-Erling Smørgravwhere 34987f5f0ecSDag-Erling Smørgrav.Fa NAME 35087f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree. 35187f5f0ecSDag-Erling SmørgravThe 35287f5f0ecSDag-Erling Smørgrav.Fa TYPE 35387f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed 35487f5f0ecSDag-Erling Smørgravby the tree. 35587f5f0ecSDag-Erling SmørgravThe 35687f5f0ecSDag-Erling Smørgrav.Fa FIELD 35787f5f0ecSDag-Erling Smørgravargument is the name of the element defined by 35887f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY . 35987f5f0ecSDag-Erling Smørgrav.Pp 36087f5f0ecSDag-Erling SmørgravThe function bodies are generated with the 36187f5f0ecSDag-Erling Smørgrav.Fn RB_GENERATE 362480565d5SRuslan Ermilovmacro. 363480565d5SRuslan ErmilovIt takes the same arguments as the 36487f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE 36587f5f0ecSDag-Erling Smørgravmacro, but should be used only once. 36687f5f0ecSDag-Erling Smørgrav.Pp 36787f5f0ecSDag-Erling SmørgravFinally, 36887f5f0ecSDag-Erling Smørgravthe 36987f5f0ecSDag-Erling Smørgrav.Fa CMP 37087f5f0ecSDag-Erling Smørgravargument is the name of a function used to compare tree noded 371480565d5SRuslan Ermilovwith each other. 372480565d5SRuslan ErmilovThe function takes two arguments of type 373480565d5SRuslan Ermilov.Vt "struct TYPE *" . 37487f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a 375480565d5SRuslan Ermilovvalue smaller than zero. 376480565d5SRuslan ErmilovIf they are equal, the function returns zero. 377480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero. 378480565d5SRuslan ErmilovThe compare 37987f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements. 38087f5f0ecSDag-Erling Smørgrav.Pp 38187f5f0ecSDag-Erling SmørgravThe 38287f5f0ecSDag-Erling Smørgrav.Fn RB_INIT 38387f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by 38487f5f0ecSDag-Erling Smørgrav.Fa head . 38587f5f0ecSDag-Erling Smørgrav.Pp 3863b96c71fSMike PritchardThe red-black tree can also be initialized statically by using the 38787f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER 38887f5f0ecSDag-Erling Smørgravmacro like this: 389480565d5SRuslan Ermilov.Bd -ragged -offset indent 390480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE 391480565d5SRuslan Ermilov.Va head 392480565d5SRuslan Ermilov= 393480565d5SRuslan Ermilov.Fn RB_INITIALIZER &head ; 39487f5f0ecSDag-Erling Smørgrav.Ed 39587f5f0ecSDag-Erling Smørgrav.Pp 39687f5f0ecSDag-Erling SmørgravThe 39787f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT 39887f5f0ecSDag-Erling Smørgravmacro inserts the new element 39987f5f0ecSDag-Erling Smørgrav.Fa elm 40087f5f0ecSDag-Erling Smørgravinto the tree. 40187f5f0ecSDag-Erling Smørgrav.Pp 40287f5f0ecSDag-Erling SmørgravThe 40387f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE 40487f5f0ecSDag-Erling Smørgravmacro removes the element 40587f5f0ecSDag-Erling Smørgrav.Fa elm 40687f5f0ecSDag-Erling Smørgravfrom the tree pointed by 40787f5f0ecSDag-Erling Smørgrav.Fa head . 40887f5f0ecSDag-Erling Smørgrav.Pp 40987f5f0ecSDag-Erling SmørgravThe 41087f5f0ecSDag-Erling Smørgrav.Fn RB_FIND 41106115e08SJason Evansand 41206115e08SJason Evans.Fn RB_NFIND 41306115e08SJason Evansmacros can be used to find a particular element in the tree. 41487f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 41587f5f0ecSDag-Erling Smørgravstruct TYPE find, *res; 41687f5f0ecSDag-Erling Smørgravfind.key = 30; 41787f5f0ecSDag-Erling Smørgravres = RB_FIND(NAME, head, &find); 41887f5f0ecSDag-Erling Smørgrav.Ed 41987f5f0ecSDag-Erling Smørgrav.Pp 42087f5f0ecSDag-Erling SmørgravThe 42187f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT , 42287f5f0ecSDag-Erling Smørgrav.Fn RB_MIN , 42387f5f0ecSDag-Erling Smørgrav.Fn RB_MAX , 42487f5f0ecSDag-Erling Smørgravand 42587f5f0ecSDag-Erling Smørgrav.Fn RB_NEXT 42687f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree: 427480565d5SRuslan Ermilov.Pp 428480565d5SRuslan Ermilov.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))" 42987f5f0ecSDag-Erling Smørgrav.Pp 43087f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the 43187f5f0ecSDag-Erling Smørgrav.Fn RB_FOREACH 43287f5f0ecSDag-Erling Smørgravmacro: 433480565d5SRuslan Ermilov.Bd -ragged -offset indent 434480565d5SRuslan Ermilov.Fn RB_FOREACH np NAME head 43587f5f0ecSDag-Erling Smørgrav.Ed 43687f5f0ecSDag-Erling Smørgrav.Pp 43787f5f0ecSDag-Erling SmørgravThe 43887f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY 439309e4b9bSDag-Erling Smørgravmacro should be used to check whether a red-black tree is empty. 44087f5f0ecSDag-Erling Smørgrav.Sh NOTES 44187f5f0ecSDag-Erling SmørgravTrying to free a tree in the following way is a common error: 44287f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 44387f5f0ecSDag-Erling SmørgravSPLAY_FOREACH(var, NAME, head) { 44487f5f0ecSDag-Erling Smørgrav SPLAY_REMOVE(NAME, head, var); 44587f5f0ecSDag-Erling Smørgrav free(var); 44687f5f0ecSDag-Erling Smørgrav} 44787f5f0ecSDag-Erling Smørgravfree(head); 44887f5f0ecSDag-Erling Smørgrav.Ed 44987f5f0ecSDag-Erling Smørgrav.Pp 45087f5f0ecSDag-Erling SmørgravSince 45187f5f0ecSDag-Erling Smørgrav.Va var 452480565d5SRuslan Ermilovis freed, the 45387f5f0ecSDag-Erling Smørgrav.Fn FOREACH 45487f5f0ecSDag-Erling Smørgravmacro refers to a pointer that may have been reallocated already. 45587f5f0ecSDag-Erling SmørgravProper code needs a second variable. 45687f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 45787f5f0ecSDag-Erling Smørgravfor (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) { 45887f5f0ecSDag-Erling Smørgrav nxt = SPLAY_NEXT(NAME, head, var); 45987f5f0ecSDag-Erling Smørgrav SPLAY_REMOVE(NAME, head, var); 46087f5f0ecSDag-Erling Smørgrav free(var); 46187f5f0ecSDag-Erling Smørgrav} 46287f5f0ecSDag-Erling Smørgrav.Ed 46387f5f0ecSDag-Erling Smørgrav.Pp 46487f5f0ecSDag-Erling SmørgravBoth 46587f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT 46687f5f0ecSDag-Erling Smørgravand 46787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT 46887f5f0ecSDag-Erling Smørgravreturn 469480565d5SRuslan Ermilov.Dv NULL 47087f5f0ecSDag-Erling Smørgravif the element was inserted in the tree successfully, otherwise they 47187f5f0ecSDag-Erling Smørgravreturn a pointer to the element with the colliding key. 47287f5f0ecSDag-Erling Smørgrav.Pp 47387f5f0ecSDag-Erling SmørgravAccordingly, 47487f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE 47587f5f0ecSDag-Erling Smørgravand 47687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE 47787f5f0ecSDag-Erling Smørgravreturn the pointer to the removed element otherwise they return 478480565d5SRuslan Ermilov.Dv NULL 47987f5f0ecSDag-Erling Smørgravto indicate an error. 48087f5f0ecSDag-Erling Smørgrav.Sh AUTHORS 481480565d5SRuslan ErmilovThe author of the tree macros is 482480565d5SRuslan Ermilov.An Niels Provos . 483