187f5f0ecSDag-Erling Smørgrav.\" $OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $ 287f5f0ecSDag-Erling Smørgrav.\"/* 387f5f0ecSDag-Erling Smørgrav.\" * Copyright 2002 Niels Provos <provos@citi.umich.edu> 487f5f0ecSDag-Erling Smørgrav.\" * All rights reserved. 587f5f0ecSDag-Erling Smørgrav.\" * 687f5f0ecSDag-Erling Smørgrav.\" * Redistribution and use in source and binary forms, with or without 787f5f0ecSDag-Erling Smørgrav.\" * modification, are permitted provided that the following conditions 887f5f0ecSDag-Erling Smørgrav.\" * are met: 987f5f0ecSDag-Erling Smørgrav.\" * 1. Redistributions of source code must retain the above copyright 1087f5f0ecSDag-Erling Smørgrav.\" * notice, this list of conditions and the following disclaimer. 1187f5f0ecSDag-Erling Smørgrav.\" * 2. Redistributions in binary form must reproduce the above copyright 1287f5f0ecSDag-Erling Smørgrav.\" * notice, this list of conditions and the following disclaimer in the 1387f5f0ecSDag-Erling Smørgrav.\" * documentation and/or other materials provided with the distribution. 1487f5f0ecSDag-Erling Smørgrav.\" * 3. All advertising materials mentioning features or use of this software 1587f5f0ecSDag-Erling Smørgrav.\" * must display the following acknowledgement: 1687f5f0ecSDag-Erling Smørgrav.\" * This product includes software developed by Niels Provos. 1787f5f0ecSDag-Erling Smørgrav.\" * 4. The name of the author may not be used to endorse or promote products 1887f5f0ecSDag-Erling Smørgrav.\" * derived from this software without specific prior written permission. 1987f5f0ecSDag-Erling Smørgrav.\" * 2087f5f0ecSDag-Erling Smørgrav.\" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2187f5f0ecSDag-Erling Smørgrav.\" * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2287f5f0ecSDag-Erling Smørgrav.\" * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2387f5f0ecSDag-Erling Smørgrav.\" * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2487f5f0ecSDag-Erling Smørgrav.\" * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2587f5f0ecSDag-Erling Smørgrav.\" * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2687f5f0ecSDag-Erling Smørgrav.\" * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2787f5f0ecSDag-Erling Smørgrav.\" * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2887f5f0ecSDag-Erling Smørgrav.\" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2987f5f0ecSDag-Erling Smørgrav.\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3087f5f0ecSDag-Erling Smørgrav.\" */ 3187f5f0ecSDag-Erling Smørgrav.Dd February 24, 2002 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, 5387f5f0ecSDag-Erling Smørgrav.Nm RB_GENERATE, 5487f5f0ecSDag-Erling Smørgrav.Nm RB_ENTRY , 5587f5f0ecSDag-Erling Smørgrav.Nm RB_HEAD , 5687f5f0ecSDag-Erling Smørgrav.Nm RB_INITIALIZER , 5787f5f0ecSDag-Erling Smørgrav.Nm RB_ROOT , 5887f5f0ecSDag-Erling Smørgrav.Nm RB_EMPTY , 5987f5f0ecSDag-Erling Smørgrav.Nm RB_NEXT , 6087f5f0ecSDag-Erling Smørgrav.Nm RB_MIN , 6187f5f0ecSDag-Erling Smørgrav.Nm RB_MAX , 6287f5f0ecSDag-Erling Smørgrav.Nm RB_FIND , 6387f5f0ecSDag-Erling Smørgrav.Nm RB_LEFT , 6487f5f0ecSDag-Erling Smørgrav.Nm RB_RIGHT , 6587f5f0ecSDag-Erling Smørgrav.Nm RB_PARENT , 6687f5f0ecSDag-Erling Smørgrav.Nm RB_FOREACH , 6787f5f0ecSDag-Erling Smørgrav.Nm RB_INIT , 6887f5f0ecSDag-Erling Smørgrav.Nm RB_INSERT , 6987f5f0ecSDag-Erling Smørgrav.Nm RB_REMOVE 7087f5f0ecSDag-Erling Smørgrav.Nd "implementations of splay and red-black trees" 7187f5f0ecSDag-Erling Smørgrav.Sh SYNOPSIS 7287f5f0ecSDag-Erling Smørgrav.Fd #include <sys/tree.h> 7387f5f0ecSDag-Erling Smørgrav.Pp 7487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" 7587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_GENERATE "NAME" "TYPE" "FIELD" "CMP" 7687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY "TYPE" 7787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD "HEADNAME" "TYPE" 7887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 7987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head" 8087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT "SPLAY_HEAD *head" 8187f5f0ecSDag-Erling Smørgrav.Ft "bool" 8287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY "SPLAY_HEAD *head" 8387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 8487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 8587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 8687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MIN "NAME" "SPLAY_HEAD *head" 8787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 8887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MAX "NAME" "SPLAY_HEAD *head" 8987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 9087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FIND "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 9187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 9287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME" 9387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 9487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" 9587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FOREACH "VARNAME" "NAME" "SPLAY_HEAD *head" 9687f5f0ecSDag-Erling Smørgrav.Ft void 9787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT "SPLAY_HEAD *head" 9887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 9987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 10087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 10187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 10287f5f0ecSDag-Erling Smørgrav.Pp 10387f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" 10487f5f0ecSDag-Erling Smørgrav.Fn RB_GENERATE "NAME" "TYPE" "FIELD" "CMP" 10587f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY "TYPE" 10687f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD "HEADNAME" "TYPE" 10787f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER "RB_HEAD *head" 10887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 10987f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT "RB_HEAD *head" 11087f5f0ecSDag-Erling Smørgrav.Ft "bool" 11187f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY "RB_HEAD *head" 11287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 11387f5f0ecSDag-Erling Smørgrav.Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm" 11487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 11587f5f0ecSDag-Erling Smørgrav.Fn RB_MIN "NAME" "RB_HEAD *head" 11687f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 11787f5f0ecSDag-Erling Smørgrav.Fn RB_MAX "NAME" "RB_HEAD *head" 11887f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 11987f5f0ecSDag-Erling Smørgrav.Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm" 12087f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 12187f5f0ecSDag-Erling Smørgrav.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" 12287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 12387f5f0ecSDag-Erling Smørgrav.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" 12487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 12587f5f0ecSDag-Erling Smørgrav.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" 12687f5f0ecSDag-Erling Smørgrav.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head" 12787f5f0ecSDag-Erling Smørgrav.Ft void 12887f5f0ecSDag-Erling Smørgrav.Fn RB_INIT "RB_HEAD *head" 12987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 13087f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT "NAME" "RB_HEAD *head" "struct TYPE *elm" 13187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 13287f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE "NAME" "RB_HEAD *head" "struct TYPE *elm" 13387f5f0ecSDag-Erling Smørgrav.Sh DESCRIPTION 13487f5f0ecSDag-Erling SmørgravThese macros defines data structures for different types of trees: 13587f5f0ecSDag-Erling Smørgravsplay trees and red-black trees. 13687f5f0ecSDag-Erling Smørgrav.Pp 13787f5f0ecSDag-Erling SmørgravIn the macro definitions, 13887f5f0ecSDag-Erling Smørgrav.Fa TYPE 13987f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must contain a field of type 14087f5f0ecSDag-Erling Smørgrav.Li SPLAY_ENTRY , 14187f5f0ecSDag-Erling Smørgravor 14287f5f0ecSDag-Erling Smørgrav.Li RB_ENTRY , 14387f5f0ecSDag-Erling Smørgravnamed 14487f5f0ecSDag-Erling Smørgrav.Fa ENTRYNAME . 14587f5f0ecSDag-Erling SmørgravThe argument 14687f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 14787f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must be declared 14887f5f0ecSDag-Erling Smørgravusing the macros 14987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD , 15087f5f0ecSDag-Erling Smørgravor 15187f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD . 15287f5f0ecSDag-Erling SmørgravThe argument 15387f5f0ecSDag-Erling Smørgrav.Fa NAME 15487f5f0ecSDag-Erling Smørgravhas to be a unique name prefix for every tree that is defined. 15587f5f0ecSDag-Erling Smørgrav.Pp 15687f5f0ecSDag-Erling SmørgravThe function prototypes are declared with either 15787f5f0ecSDag-Erling Smørgrav.Li SPLAY_PROTOTYPE, 15887f5f0ecSDag-Erling Smørgravor 15987f5f0ecSDag-Erling Smørgrav.Li RB_PROTOTYPE . 16087f5f0ecSDag-Erling SmørgravThe function bodies are generated with either 16187f5f0ecSDag-Erling Smørgrav.Li SPLAY_GENERATE, 16287f5f0ecSDag-Erling Smørgravor 16387f5f0ecSDag-Erling Smørgrav.Li RB_GENERATE . 16487f5f0ecSDag-Erling SmørgravSee the examples below for further explanation of how these macros are used. 16587f5f0ecSDag-Erling Smørgrav.Sh SPLAY TREES 16687f5f0ecSDag-Erling SmørgravA splay tree is a self-organizing data structure. Every operation 16787f5f0ecSDag-Erling Smørgravon the tree causes a splay to happen. The splay moves the requested 16887f5f0ecSDag-Erling Smørgravnode to the root of the tree and partly rebalances it. 16987f5f0ecSDag-Erling Smørgrav.Pp 17087f5f0ecSDag-Erling SmørgravThis has the benefit that request locality causes faster lookups as 17187f5f0ecSDag-Erling Smørgravthe requested nodes move to the top of the tree. On the other hand, 17287f5f0ecSDag-Erling Smørgravevery lookup causes memory writes. 17387f5f0ecSDag-Erling Smørgrav.Pp 17487f5f0ecSDag-Erling SmørgravThe Balance Theorem bounds the total access time for m operations 17587f5f0ecSDag-Erling Smørgravand n inserts on an initially empty tree as O((m + n)lg n). The 17687f5f0ecSDag-Erling Smørgravamortized cost for a sequence of m accesses to a splay tree is O(lg n); 17787f5f0ecSDag-Erling Smørgrav.Pp 17887f5f0ecSDag-Erling SmørgravA splay tree is headed by a structure defined by the 17987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD 18087f5f0ecSDag-Erling Smørgravmacro. 18187f5f0ecSDag-Erling SmørgravA 18287f5f0ecSDag-Erling Smørgrav.Fa SPLAY_HEAD 18387f5f0ecSDag-Erling Smørgravstructure is declared as follows: 18487f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 18587f5f0ecSDag-Erling SmørgravSPLAY_HEAD(HEADNAME, TYPE) head; 18687f5f0ecSDag-Erling Smørgrav.Ed 18787f5f0ecSDag-Erling Smørgrav.Pp 18887f5f0ecSDag-Erling Smørgravwhere 18987f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 19087f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct 19187f5f0ecSDag-Erling Smørgrav.Fa TYPE 19287f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree. 19387f5f0ecSDag-Erling Smørgrav.Pp 19487f5f0ecSDag-Erling SmørgravThe 19587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY 19687f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree. 19787f5f0ecSDag-Erling Smørgrav.Pp 19887f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure, 19987f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the 20087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE 20187f5f0ecSDag-Erling Smørgravmacro, 20287f5f0ecSDag-Erling Smørgravwhere 20387f5f0ecSDag-Erling Smørgrav.Fa NAME 20487f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree. 20587f5f0ecSDag-Erling SmørgravThe 20687f5f0ecSDag-Erling Smørgrav.Fa TYPE 20787f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed 20887f5f0ecSDag-Erling Smørgravby the tree. 20987f5f0ecSDag-Erling SmørgravThe 21087f5f0ecSDag-Erling Smørgrav.Fa FIELD 21187f5f0ecSDag-Erling Smørgravargument is the name of the element defined by 21287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY . 21387f5f0ecSDag-Erling Smørgrav.Pp 21487f5f0ecSDag-Erling SmørgravThe function bodies are generated with the 21587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_GENERATE 21687f5f0ecSDag-Erling Smørgravmacro. It takes the same arguments as the 21787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE 21887f5f0ecSDag-Erling Smørgravmacro, but should be used only once. 21987f5f0ecSDag-Erling Smørgrav.Pp 22087f5f0ecSDag-Erling SmørgravFinally, 22187f5f0ecSDag-Erling Smørgravthe 22287f5f0ecSDag-Erling Smørgrav.Fa CMP 22387f5f0ecSDag-Erling Smørgravargument is the name of a function used to compare tree noded 22487f5f0ecSDag-Erling Smørgravwith each other. The function takes two arguments of type 22587f5f0ecSDag-Erling Smørgrav.Fa "struct TYPE *" . 22687f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a 22787f5f0ecSDag-Erling Smørgravvalue smaller than zero. If they are equal, the function returns zero. 22887f5f0ecSDag-Erling SmørgravOtherwise, it should return a value greater than zero. The compare 22987f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements. 23087f5f0ecSDag-Erling Smørgrav.Pp 23187f5f0ecSDag-Erling SmørgravThe 23287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT 23387f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by 23487f5f0ecSDag-Erling Smørgrav.Fa head . 23587f5f0ecSDag-Erling Smørgrav.Pp 23687f5f0ecSDag-Erling SmørgravThe splay tree can also be initialized statically by using the 23787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER 23887f5f0ecSDag-Erling Smørgravmacro like this: 23987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 24087f5f0ecSDag-Erling SmørgravSPLAY_HEAD(HEADNAME, TYPE) head = SPLAY_INITIALIZER(&head); 24187f5f0ecSDag-Erling Smørgrav.Ed 24287f5f0ecSDag-Erling Smørgrav.Pp 24387f5f0ecSDag-Erling SmørgravThe 24487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT 24587f5f0ecSDag-Erling Smørgravmacro inserts the new element 24687f5f0ecSDag-Erling Smørgrav.Fa elm 24787f5f0ecSDag-Erling Smørgravinto the tree. 24887f5f0ecSDag-Erling Smørgrav.Pp 24987f5f0ecSDag-Erling SmørgravThe 25087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE 25187f5f0ecSDag-Erling Smørgravmacro removes the element 25287f5f0ecSDag-Erling Smørgrav.Fa elm 25387f5f0ecSDag-Erling Smørgravfrom the tree pointed by 25487f5f0ecSDag-Erling Smørgrav.Fa head . 25587f5f0ecSDag-Erling Smørgrav.Pp 25687f5f0ecSDag-Erling SmørgravThe 25787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FIND 25887f5f0ecSDag-Erling Smørgravmacro can be used to find a particular element in the tree. 25987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 26087f5f0ecSDag-Erling Smørgravstruct TYPE find, *res; 26187f5f0ecSDag-Erling Smørgravfind.key = 30; 26287f5f0ecSDag-Erling Smørgravres = SPLAY_FIND(NAME, head, &find); 26387f5f0ecSDag-Erling Smørgrav.Ed 26487f5f0ecSDag-Erling Smørgrav.Pp 26587f5f0ecSDag-Erling SmørgravThe 26687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT , 26787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MIN , 26887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MAX , 26987f5f0ecSDag-Erling Smørgravand 27087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_NEXT 27187f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree: 27287f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 27387f5f0ecSDag-Erling Smørgravfor (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np)) 27487f5f0ecSDag-Erling Smørgrav.Ed 27587f5f0ecSDag-Erling Smørgrav.Pp 27687f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the 27787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FOREACH 27887f5f0ecSDag-Erling Smørgravmacro: 27987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 28087f5f0ecSDag-Erling SmørgravSPLAY_FOREACH(np, NAME, head) 28187f5f0ecSDag-Erling Smørgrav.Ed 28287f5f0ecSDag-Erling Smørgrav.Pp 28387f5f0ecSDag-Erling SmørgravThe 28487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY 28587f5f0ecSDag-Erling Smørgravmacro should be used to check whether a splay tree is empty. 28687f5f0ecSDag-Erling Smørgrav.Pp 28787f5f0ecSDag-Erling Smørgrav.Sh RED-BLACK TREES 28887f5f0ecSDag-Erling SmørgravA red-black tree is a binary search tree with the node color as an 28987f5f0ecSDag-Erling Smørgravextra attribute. It fulfills a set of conditions: 29087f5f0ecSDag-Erling Smørgrav.Bl -enum -compact -offset indent 29187f5f0ecSDag-Erling Smørgrav.It 29287f5f0ecSDag-Erling Smørgravevery search path from the root to a leaf consists of the same number of 29387f5f0ecSDag-Erling Smørgravblack nodes, 29487f5f0ecSDag-Erling Smørgrav.It 29587f5f0ecSDag-Erling Smørgraveach red node (except for the root) has a black parent, 29687f5f0ecSDag-Erling Smørgrav.It 29787f5f0ecSDag-Erling Smørgraveach leaf node is black. 29887f5f0ecSDag-Erling Smørgrav.El 29987f5f0ecSDag-Erling Smørgrav.Pp 30087f5f0ecSDag-Erling SmørgravEvery operation on a red-black tree is bounded as O(lg n). 30187f5f0ecSDag-Erling SmørgravThe maximum height of a red-black tree is 2lg (n+1). 30287f5f0ecSDag-Erling Smørgrav.Pp 30387f5f0ecSDag-Erling SmørgravA red-black tree is headed by a structure defined by the 30487f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD 30587f5f0ecSDag-Erling Smørgravmacro. 30687f5f0ecSDag-Erling SmørgravA 30787f5f0ecSDag-Erling Smørgrav.Fa RB_HEAD 30887f5f0ecSDag-Erling Smørgravstructure is declared as follows: 30987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 31087f5f0ecSDag-Erling SmørgravRB_HEAD(HEADNAME, TYPE) head; 31187f5f0ecSDag-Erling Smørgrav.Ed 31287f5f0ecSDag-Erling Smørgrav.Pp 31387f5f0ecSDag-Erling Smørgravwhere 31487f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 31587f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct 31687f5f0ecSDag-Erling Smørgrav.Fa TYPE 31787f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree. 31887f5f0ecSDag-Erling Smørgrav.Pp 31987f5f0ecSDag-Erling SmørgravThe 32087f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY 32187f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree. 32287f5f0ecSDag-Erling Smørgrav.Pp 32387f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure, 32487f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the 32587f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE 32687f5f0ecSDag-Erling Smørgravmacro, 32787f5f0ecSDag-Erling Smørgravwhere 32887f5f0ecSDag-Erling Smørgrav.Fa NAME 32987f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree. 33087f5f0ecSDag-Erling SmørgravThe 33187f5f0ecSDag-Erling Smørgrav.Fa TYPE 33287f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed 33387f5f0ecSDag-Erling Smørgravby the tree. 33487f5f0ecSDag-Erling SmørgravThe 33587f5f0ecSDag-Erling Smørgrav.Fa FIELD 33687f5f0ecSDag-Erling Smørgravargument is the name of the element defined by 33787f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY . 33887f5f0ecSDag-Erling Smørgrav.Pp 33987f5f0ecSDag-Erling SmørgravThe function bodies are generated with the 34087f5f0ecSDag-Erling Smørgrav.Fn RB_GENERATE 34187f5f0ecSDag-Erling Smørgravmacro. It takes the same arguments as the 34287f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE 34387f5f0ecSDag-Erling Smørgravmacro, but should be used only once. 34487f5f0ecSDag-Erling Smørgrav.Pp 34587f5f0ecSDag-Erling SmørgravFinally, 34687f5f0ecSDag-Erling Smørgravthe 34787f5f0ecSDag-Erling Smørgrav.Fa CMP 34887f5f0ecSDag-Erling Smørgravargument is the name of a function used to compare tree noded 34987f5f0ecSDag-Erling Smørgravwith each other. The function takes two arguments of type 35087f5f0ecSDag-Erling Smørgrav.Fa "struct TYPE *" . 35187f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a 35287f5f0ecSDag-Erling Smørgravvalue smaller than zero. If they are equal, the function returns zero. 35387f5f0ecSDag-Erling SmørgravOtherwise, it should return a value greater than zero. The compare 35487f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements. 35587f5f0ecSDag-Erling Smørgrav.Pp 35687f5f0ecSDag-Erling SmørgravThe 35787f5f0ecSDag-Erling Smørgrav.Fn RB_INIT 35887f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by 35987f5f0ecSDag-Erling Smørgrav.Fa head . 36087f5f0ecSDag-Erling Smørgrav.Pp 36187f5f0ecSDag-Erling SmørgravThe redblack tree can also be initialized statically by using the 36287f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER 36387f5f0ecSDag-Erling Smørgravmacro like this: 36487f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 36587f5f0ecSDag-Erling SmørgravRB_HEAD(HEADNAME, TYPE) head = RB_INITIALIZER(&head); 36687f5f0ecSDag-Erling Smørgrav.Ed 36787f5f0ecSDag-Erling Smørgrav.Pp 36887f5f0ecSDag-Erling SmørgravThe 36987f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT 37087f5f0ecSDag-Erling Smørgravmacro inserts the new element 37187f5f0ecSDag-Erling Smørgrav.Fa elm 37287f5f0ecSDag-Erling Smørgravinto the tree. 37387f5f0ecSDag-Erling Smørgrav.Pp 37487f5f0ecSDag-Erling SmørgravThe 37587f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE 37687f5f0ecSDag-Erling Smørgravmacro removes the element 37787f5f0ecSDag-Erling Smørgrav.Fa elm 37887f5f0ecSDag-Erling Smørgravfrom the tree pointed by 37987f5f0ecSDag-Erling Smørgrav.Fa head . 38087f5f0ecSDag-Erling Smørgrav.Pp 38187f5f0ecSDag-Erling SmørgravThe 38287f5f0ecSDag-Erling Smørgrav.Fn RB_FIND 38387f5f0ecSDag-Erling Smørgravmacro can be used to find a particular element in the tree. 38487f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 38587f5f0ecSDag-Erling Smørgravstruct TYPE find, *res; 38687f5f0ecSDag-Erling Smørgravfind.key = 30; 38787f5f0ecSDag-Erling Smørgravres = RB_FIND(NAME, head, &find); 38887f5f0ecSDag-Erling Smørgrav.Ed 38987f5f0ecSDag-Erling Smørgrav.Pp 39087f5f0ecSDag-Erling SmørgravThe 39187f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT , 39287f5f0ecSDag-Erling Smørgrav.Fn RB_MIN , 39387f5f0ecSDag-Erling Smørgrav.Fn RB_MAX , 39487f5f0ecSDag-Erling Smørgravand 39587f5f0ecSDag-Erling Smørgrav.Fn RB_NEXT 39687f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree: 39787f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 39887f5f0ecSDag-Erling Smørgravfor (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np)) 39987f5f0ecSDag-Erling Smørgrav.Ed 40087f5f0ecSDag-Erling Smørgrav.Pp 40187f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the 40287f5f0ecSDag-Erling Smørgrav.Fn RB_FOREACH 40387f5f0ecSDag-Erling Smørgravmacro: 40487f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 40587f5f0ecSDag-Erling SmørgravRB_FOREACH(np, NAME, head) 40687f5f0ecSDag-Erling Smørgrav.Ed 40787f5f0ecSDag-Erling Smørgrav.Pp 40887f5f0ecSDag-Erling SmørgravThe 40987f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY 41087f5f0ecSDag-Erling Smørgravmacro should be used to check whether a splay tree is empty. 41187f5f0ecSDag-Erling Smørgrav.Pp 41287f5f0ecSDag-Erling Smørgrav.Sh NOTES 41387f5f0ecSDag-Erling SmørgravTrying to free a tree in the following way is a common error: 41487f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 41587f5f0ecSDag-Erling SmørgravSPLAY_FOREACH(var, NAME, head) { 41687f5f0ecSDag-Erling Smørgrav SPLAY_REMOVE(NAME, head, var); 41787f5f0ecSDag-Erling Smørgrav free(var); 41887f5f0ecSDag-Erling Smørgrav} 41987f5f0ecSDag-Erling Smørgravfree(head); 42087f5f0ecSDag-Erling Smørgrav.Ed 42187f5f0ecSDag-Erling Smørgrav.Pp 42287f5f0ecSDag-Erling SmørgravSince 42387f5f0ecSDag-Erling Smørgrav.Va var 42487f5f0ecSDag-Erling Smørgravis free'd, the 42587f5f0ecSDag-Erling Smørgrav.Fn FOREACH 42687f5f0ecSDag-Erling Smørgravmacro refers to a pointer that may have been reallocated already. 42787f5f0ecSDag-Erling SmørgravProper code needs a second variable. 42887f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 42987f5f0ecSDag-Erling Smørgravfor (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) { 43087f5f0ecSDag-Erling Smørgrav nxt = SPLAY_NEXT(NAME, head, var); 43187f5f0ecSDag-Erling Smørgrav SPLAY_REMOVE(NAME, head, var); 43287f5f0ecSDag-Erling Smørgrav free(var); 43387f5f0ecSDag-Erling Smørgrav} 43487f5f0ecSDag-Erling Smørgrav.Ed 43587f5f0ecSDag-Erling Smørgrav.Pp 43687f5f0ecSDag-Erling SmørgravBoth 43787f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT 43887f5f0ecSDag-Erling Smørgravand 43987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT 44087f5f0ecSDag-Erling Smørgravreturn 44187f5f0ecSDag-Erling Smørgrav.Va NULL 44287f5f0ecSDag-Erling Smørgravif the element was inserted in the tree successfully, otherwise they 44387f5f0ecSDag-Erling Smørgravreturn a pointer to the element with the colliding key. 44487f5f0ecSDag-Erling Smørgrav.Pp 44587f5f0ecSDag-Erling SmørgravAccordingly, 44687f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE 44787f5f0ecSDag-Erling Smørgravand 44887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE 44987f5f0ecSDag-Erling Smørgravreturn the pointer to the removed element otherwise they return 45087f5f0ecSDag-Erling Smørgrav.Va NULL 45187f5f0ecSDag-Erling Smørgravto indicate an error. 45287f5f0ecSDag-Erling Smørgrav.Sh AUTHORS 45387f5f0ecSDag-Erling SmørgravThe author of the tree macros is Niels Provos. 454