1d19613acSJoerg Sonnenberger.\" $NetBSD: tree.3,v 1.3 2004/04/14 11:05:19 pooka Exp $ 2d19613acSJoerg Sonnenberger.\" $OpenBSD: tree.3,v 1.9 2003/05/20 09:13:38 jmc Exp $ 3d19613acSJoerg Sonnenberger.\"/* 4d19613acSJoerg Sonnenberger.\" * Copyright 2002 Niels Provos <provos@citi.umich.edu> 5d19613acSJoerg Sonnenberger.\" * All rights reserved. 6d19613acSJoerg Sonnenberger.\" * 7d19613acSJoerg Sonnenberger.\" * Redistribution and use in source and binary forms, with or without 8d19613acSJoerg Sonnenberger.\" * modification, are permitted provided that the following conditions 9d19613acSJoerg Sonnenberger.\" * are met: 10d19613acSJoerg Sonnenberger.\" * 1. Redistributions of source code must retain the above copyright 11d19613acSJoerg Sonnenberger.\" * notice, this list of conditions and the following disclaimer. 12d19613acSJoerg Sonnenberger.\" * 2. Redistributions in binary form must reproduce the above copyright 13d19613acSJoerg Sonnenberger.\" * notice, this list of conditions and the following disclaimer in the 14d19613acSJoerg Sonnenberger.\" * documentation and/or other materials provided with the distribution. 15d19613acSJoerg Sonnenberger.\" * 3. All advertising materials mentioning features or use of this software 16d19613acSJoerg Sonnenberger.\" * must display the following acknowledgement: 17d19613acSJoerg Sonnenberger.\" * This product includes software developed by Niels Provos. 18d19613acSJoerg Sonnenberger.\" * 4. The name of the author may not be used to endorse or promote products 19d19613acSJoerg Sonnenberger.\" * derived from this software without specific prior written permission. 20d19613acSJoerg Sonnenberger.\" * 21d19613acSJoerg Sonnenberger.\" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22d19613acSJoerg Sonnenberger.\" * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23d19613acSJoerg Sonnenberger.\" * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24d19613acSJoerg Sonnenberger.\" * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25d19613acSJoerg Sonnenberger.\" * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26d19613acSJoerg Sonnenberger.\" * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27d19613acSJoerg Sonnenberger.\" * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28d19613acSJoerg Sonnenberger.\" * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29d19613acSJoerg Sonnenberger.\" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30d19613acSJoerg Sonnenberger.\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31d19613acSJoerg Sonnenberger.\" */ 32*37149c60SSascha Wildner.Dd August 9, 2015 33d19613acSJoerg Sonnenberger.Dt TREE 3 34d19613acSJoerg Sonnenberger.Os 35d19613acSJoerg Sonnenberger.Sh NAME 36d19613acSJoerg Sonnenberger.Nm SPLAY_PROTOTYPE , 37d19613acSJoerg Sonnenberger.Nm SPLAY_GENERATE , 38d19613acSJoerg Sonnenberger.Nm SPLAY_ENTRY , 39d19613acSJoerg Sonnenberger.Nm SPLAY_HEAD , 40d19613acSJoerg Sonnenberger.Nm SPLAY_INITIALIZER , 41d19613acSJoerg Sonnenberger.Nm SPLAY_ROOT , 42d19613acSJoerg Sonnenberger.Nm SPLAY_EMPTY , 43d19613acSJoerg Sonnenberger.Nm SPLAY_NEXT , 44d19613acSJoerg Sonnenberger.Nm SPLAY_MIN , 45d19613acSJoerg Sonnenberger.Nm SPLAY_MAX , 46d19613acSJoerg Sonnenberger.Nm SPLAY_FIND , 47d19613acSJoerg Sonnenberger.Nm SPLAY_LEFT , 48d19613acSJoerg Sonnenberger.Nm SPLAY_RIGHT , 49d19613acSJoerg Sonnenberger.Nm SPLAY_FOREACH , 50d19613acSJoerg Sonnenberger.Nm SPLAY_INIT , 51d19613acSJoerg Sonnenberger.Nm SPLAY_INSERT , 52d19613acSJoerg Sonnenberger.Nm SPLAY_REMOVE , 53d19613acSJoerg Sonnenberger.Nm RB_PROTOTYPE , 54d19613acSJoerg Sonnenberger.Nm RB_GENERATE , 55d19613acSJoerg Sonnenberger.Nm RB_ENTRY , 56d19613acSJoerg Sonnenberger.Nm RB_HEAD , 57d19613acSJoerg Sonnenberger.Nm RB_INITIALIZER , 58d19613acSJoerg Sonnenberger.Nm RB_ROOT , 59d19613acSJoerg Sonnenberger.Nm RB_EMPTY , 60d19613acSJoerg Sonnenberger.Nm RB_NEXT , 61d19613acSJoerg Sonnenberger.Nm RB_MIN , 62d19613acSJoerg Sonnenberger.Nm RB_MAX , 63d19613acSJoerg Sonnenberger.Nm RB_FIND , 64d19613acSJoerg Sonnenberger.Nm RB_LEFT , 65d19613acSJoerg Sonnenberger.Nm RB_RIGHT , 66d19613acSJoerg Sonnenberger.Nm RB_PARENT , 67d19613acSJoerg Sonnenberger.Nm RB_FOREACH , 68*37149c60SSascha Wildner.Nm RB_FOREACH_FROM , 69*37149c60SSascha Wildner.Nm RB_FOREACH_SAFE , 70*37149c60SSascha Wildner.Nm RB_FOREACH_REVERSE , 71*37149c60SSascha Wildner.Nm RB_FOREACH_REVERSE_FROM , 72*37149c60SSascha Wildner.Nm RB_FOREACH_REVERSE_SAFE , 73d19613acSJoerg Sonnenberger.Nm RB_INIT , 74d19613acSJoerg Sonnenberger.Nm RB_INSERT , 75d19613acSJoerg Sonnenberger.Nm RB_REMOVE 76d19613acSJoerg Sonnenberger.Nd implementations of splay and red-black trees 77d19613acSJoerg Sonnenberger.Sh SYNOPSIS 78d19613acSJoerg Sonnenberger.In sys/tree.h 79d19613acSJoerg Sonnenberger.Fn SPLAY_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" 80d19613acSJoerg Sonnenberger.Fn SPLAY_GENERATE "NAME" "TYPE" "FIELD" "CMP" 81d19613acSJoerg Sonnenberger.Fn SPLAY_ENTRY "TYPE" 82d19613acSJoerg Sonnenberger.Fn SPLAY_HEAD "HEADNAME" "TYPE" 83d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 84d19613acSJoerg Sonnenberger.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head" 85d19613acSJoerg Sonnenberger.Fn SPLAY_ROOT "SPLAY_HEAD *head" 86d19613acSJoerg Sonnenberger.Ft "bool" 87d19613acSJoerg Sonnenberger.Fn SPLAY_EMPTY "SPLAY_HEAD *head" 88d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 89d19613acSJoerg Sonnenberger.Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 90d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 91d19613acSJoerg Sonnenberger.Fn SPLAY_MIN "NAME" "SPLAY_HEAD *head" 92d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 93d19613acSJoerg Sonnenberger.Fn SPLAY_MAX "NAME" "SPLAY_HEAD *head" 94d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 95d19613acSJoerg Sonnenberger.Fn SPLAY_FIND "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 96d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 97d19613acSJoerg Sonnenberger.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME" 98d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 99d19613acSJoerg Sonnenberger.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" 100d19613acSJoerg Sonnenberger.Fn SPLAY_FOREACH "VARNAME" "NAME" "SPLAY_HEAD *head" 101d19613acSJoerg Sonnenberger.Ft void 102d19613acSJoerg Sonnenberger.Fn SPLAY_INIT "SPLAY_HEAD *head" 103d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 104d19613acSJoerg Sonnenberger.Fn SPLAY_INSERT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 105d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 106d19613acSJoerg Sonnenberger.Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 107d19613acSJoerg Sonnenberger.Pp 108d19613acSJoerg Sonnenberger.Fn RB_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" 109d19613acSJoerg Sonnenberger.Fn RB_GENERATE "NAME" "TYPE" "FIELD" "CMP" 110d19613acSJoerg Sonnenberger.Fn RB_ENTRY "TYPE" 111d19613acSJoerg Sonnenberger.Fn RB_HEAD "HEADNAME" "TYPE" 112d19613acSJoerg Sonnenberger.Fn RB_INITIALIZER "RB_HEAD *head" 113d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 114d19613acSJoerg Sonnenberger.Fn RB_ROOT "RB_HEAD *head" 115d19613acSJoerg Sonnenberger.Ft "bool" 116d19613acSJoerg Sonnenberger.Fn RB_EMPTY "RB_HEAD *head" 117d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 118d19613acSJoerg Sonnenberger.Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm" 119d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 120d19613acSJoerg Sonnenberger.Fn RB_MIN "NAME" "RB_HEAD *head" 121d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 122d19613acSJoerg Sonnenberger.Fn RB_MAX "NAME" "RB_HEAD *head" 123d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 124d19613acSJoerg Sonnenberger.Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm" 125d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 126d19613acSJoerg Sonnenberger.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" 127d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 128d19613acSJoerg Sonnenberger.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" 129d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 130d19613acSJoerg Sonnenberger.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" 131d19613acSJoerg Sonnenberger.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head" 132*37149c60SSascha Wildner.Fn RB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME" 133*37149c60SSascha Wildner.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 134*37149c60SSascha Wildner.Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head" 135*37149c60SSascha Wildner.Fn RB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME" 136*37149c60SSascha Wildner.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 137d19613acSJoerg Sonnenberger.Ft void 138d19613acSJoerg Sonnenberger.Fn RB_INIT "RB_HEAD *head" 139d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 140d19613acSJoerg Sonnenberger.Fn RB_INSERT "NAME" "RB_HEAD *head" "struct TYPE *elm" 141d19613acSJoerg Sonnenberger.Ft "struct TYPE *" 142d19613acSJoerg Sonnenberger.Fn RB_REMOVE "NAME" "RB_HEAD *head" "struct TYPE *elm" 143d19613acSJoerg Sonnenberger.Sh DESCRIPTION 144d19613acSJoerg SonnenbergerThese macros define data structures for different types of trees: 145d19613acSJoerg Sonnenbergersplay trees and red-black trees. 146d19613acSJoerg Sonnenberger.Pp 147d19613acSJoerg SonnenbergerIn the macro definitions, 148d19613acSJoerg Sonnenberger.Fa TYPE 149d19613acSJoerg Sonnenbergeris the name tag of a user defined structure that must contain a field of type 150d19613acSJoerg Sonnenberger.Li SPLAY_ENTRY , 151d19613acSJoerg Sonnenbergeror 152d19613acSJoerg Sonnenberger.Li RB_ENTRY , 153d19613acSJoerg Sonnenbergernamed 154d19613acSJoerg Sonnenberger.Fa ENTRYNAME . 155d19613acSJoerg SonnenbergerThe argument 156d19613acSJoerg Sonnenberger.Fa HEADNAME 157d19613acSJoerg Sonnenbergeris the name tag of a user defined structure that must be declared 158d19613acSJoerg Sonnenbergerusing the macros 159d19613acSJoerg Sonnenberger.Fn SPLAY_HEAD 160d19613acSJoerg Sonnenbergeror 161d19613acSJoerg Sonnenberger.Fn RB_HEAD . 162d19613acSJoerg SonnenbergerThe argument 163d19613acSJoerg Sonnenberger.Fa NAME 164d19613acSJoerg Sonnenbergerhas to be a unique name prefix for every tree that is defined. 165d19613acSJoerg Sonnenberger.Pp 166d19613acSJoerg SonnenbergerThe function prototypes are declared with either 167d19613acSJoerg Sonnenberger.Li SPLAY_PROTOTYPE 168d19613acSJoerg Sonnenbergeror 169d19613acSJoerg Sonnenberger.Li RB_PROTOTYPE . 170d19613acSJoerg SonnenbergerThe function bodies are generated with either 171d19613acSJoerg Sonnenberger.Li SPLAY_GENERATE 172d19613acSJoerg Sonnenbergeror 173d19613acSJoerg Sonnenberger.Li RB_GENERATE . 174d19613acSJoerg SonnenbergerSee the examples below for further explanation of how these macros are used. 175d19613acSJoerg Sonnenberger.Sh SPLAY TREES 176d19613acSJoerg SonnenbergerA splay tree is a self-organizing data structure. 177d19613acSJoerg SonnenbergerEvery operation on the tree causes a splay to happen. 178d19613acSJoerg SonnenbergerThe splay moves the requested node to the root of the tree and partly 179d19613acSJoerg Sonnenbergerrebalances it. 180d19613acSJoerg Sonnenberger.Pp 181d19613acSJoerg SonnenbergerThis has the benefit that request locality causes faster lookups as 182d19613acSJoerg Sonnenbergerthe requested nodes move to the top of the tree. 183d19613acSJoerg SonnenbergerOn the other hand, every lookup causes memory writes. 184d19613acSJoerg Sonnenberger.Pp 185d19613acSJoerg SonnenbergerThe Balance Theorem bounds the total access time for m operations 186d19613acSJoerg Sonnenbergerand n inserts on an initially empty tree as O((m + n)lg n). 187d19613acSJoerg SonnenbergerThe amortized cost for a sequence of m accesses to a splay tree is O(lg n). 188d19613acSJoerg Sonnenberger.Pp 189d19613acSJoerg SonnenbergerA splay tree is headed by a structure defined by the 190d19613acSJoerg Sonnenberger.Fn SPLAY_HEAD 191d19613acSJoerg Sonnenbergermacro. 192d19613acSJoerg SonnenbergerA 193d19613acSJoerg Sonnenberger.Fa SPLAY_HEAD 194d19613acSJoerg Sonnenbergerstructure is declared as follows: 195d19613acSJoerg Sonnenberger.Bd -literal -offset indent 196d19613acSJoerg SonnenbergerSPLAY_HEAD(HEADNAME, TYPE) head; 197d19613acSJoerg Sonnenberger.Ed 198d19613acSJoerg Sonnenberger.Pp 199d19613acSJoerg Sonnenbergerwhere 200d19613acSJoerg Sonnenberger.Fa HEADNAME 201d19613acSJoerg Sonnenbergeris the name of the structure to be defined, and struct 202d19613acSJoerg Sonnenberger.Fa TYPE 203d19613acSJoerg Sonnenbergeris the type of the elements to be inserted into the tree. 204d19613acSJoerg Sonnenberger.Pp 205d19613acSJoerg SonnenbergerThe 206d19613acSJoerg Sonnenberger.Fn SPLAY_ENTRY 207d19613acSJoerg Sonnenbergermacro declares a structure that allows elements to be connected in the tree. 208d19613acSJoerg Sonnenberger.Pp 209d19613acSJoerg SonnenbergerIn order to use the functions that manipulate the tree structure, 210d19613acSJoerg Sonnenbergertheir prototypes need to be declared with the 211d19613acSJoerg Sonnenberger.Fn SPLAY_PROTOTYPE 212d19613acSJoerg Sonnenbergermacro, 213d19613acSJoerg Sonnenbergerwhere 214d19613acSJoerg Sonnenberger.Fa NAME 215d19613acSJoerg Sonnenbergeris a unique identifier for this particular tree. 216d19613acSJoerg SonnenbergerThe 217d19613acSJoerg Sonnenberger.Fa TYPE 218d19613acSJoerg Sonnenbergerargument is the type of the structure that is being managed 219d19613acSJoerg Sonnenbergerby the tree. 220d19613acSJoerg SonnenbergerThe 221d19613acSJoerg Sonnenberger.Fa FIELD 222d19613acSJoerg Sonnenbergerargument is the name of the element defined by 223d19613acSJoerg Sonnenberger.Fn SPLAY_ENTRY . 224d19613acSJoerg Sonnenberger.Pp 225d19613acSJoerg SonnenbergerThe function bodies are generated with the 226d19613acSJoerg Sonnenberger.Fn SPLAY_GENERATE 227d19613acSJoerg Sonnenbergermacro. 228d19613acSJoerg SonnenbergerIt takes the same arguments as the 229d19613acSJoerg Sonnenberger.Fn SPLAY_PROTOTYPE 230d19613acSJoerg Sonnenbergermacro, but should be used only once. 231d19613acSJoerg Sonnenberger.Pp 232d19613acSJoerg SonnenbergerFinally, 233d19613acSJoerg Sonnenbergerthe 234d19613acSJoerg Sonnenberger.Fa CMP 235d19613acSJoerg Sonnenbergerargument is the name of a function used to compare trees noded 236d19613acSJoerg Sonnenbergerwith each other. 237d19613acSJoerg SonnenbergerThe function takes two arguments of type 238d19613acSJoerg Sonnenberger.Fa "struct TYPE *" . 239d19613acSJoerg SonnenbergerIf the first argument is smaller than the second, the function returns a 240d19613acSJoerg Sonnenbergervalue smaller than zero. 241d19613acSJoerg SonnenbergerIf they are equal, the function returns zero. 242d19613acSJoerg SonnenbergerOtherwise, it should return a value greater than zero. 243d19613acSJoerg SonnenbergerThe compare function defines the order of the tree elements. 244d19613acSJoerg Sonnenberger.Pp 245d19613acSJoerg SonnenbergerThe 246d19613acSJoerg Sonnenberger.Fn SPLAY_INIT 247d19613acSJoerg Sonnenbergermacro initializes the tree referenced by 248d19613acSJoerg Sonnenberger.Fa head . 249d19613acSJoerg Sonnenberger.Pp 250d19613acSJoerg SonnenbergerThe splay tree can also be initialized statically by using the 251d19613acSJoerg Sonnenberger.Fn SPLAY_INITIALIZER 252d19613acSJoerg Sonnenbergermacro like this: 253d19613acSJoerg Sonnenberger.Bd -literal -offset indent 254d19613acSJoerg SonnenbergerSPLAY_HEAD(HEADNAME, TYPE) head = SPLAY_INITIALIZER(\*[Am]head); 255d19613acSJoerg Sonnenberger.Ed 256d19613acSJoerg Sonnenberger.Pp 257d19613acSJoerg SonnenbergerThe 258d19613acSJoerg Sonnenberger.Fn SPLAY_INSERT 259d19613acSJoerg Sonnenbergermacro inserts the new element 260d19613acSJoerg Sonnenberger.Fa elm 261d19613acSJoerg Sonnenbergerinto the tree. 262d19613acSJoerg Sonnenberger.Pp 263d19613acSJoerg SonnenbergerThe 264d19613acSJoerg Sonnenberger.Fn SPLAY_REMOVE 265d19613acSJoerg Sonnenbergermacro removes the element 266d19613acSJoerg Sonnenberger.Fa elm 267d19613acSJoerg Sonnenbergerfrom the tree pointed by 268d19613acSJoerg Sonnenberger.Fa head . 269d19613acSJoerg Sonnenberger.Pp 270d19613acSJoerg SonnenbergerThe 271d19613acSJoerg Sonnenberger.Fn SPLAY_FIND 272d19613acSJoerg Sonnenbergermacro can be used to find a particular element in the tree. 273d19613acSJoerg Sonnenberger.Bd -literal -offset indent 274d19613acSJoerg Sonnenbergerstruct TYPE find, *res; 275d19613acSJoerg Sonnenbergerfind.key = 30; 276d19613acSJoerg Sonnenbergerres = SPLAY_FIND(NAME, head, \*[Am]find); 277d19613acSJoerg Sonnenberger.Ed 278d19613acSJoerg Sonnenberger.Pp 279d19613acSJoerg SonnenbergerThe 280d19613acSJoerg Sonnenberger.Fn SPLAY_ROOT , 281d19613acSJoerg Sonnenberger.Fn SPLAY_MIN , 282d19613acSJoerg Sonnenberger.Fn SPLAY_MAX , 283d19613acSJoerg Sonnenbergerand 284d19613acSJoerg Sonnenberger.Fn SPLAY_NEXT 285d19613acSJoerg Sonnenbergermacros can be used to traverse the tree: 286d19613acSJoerg Sonnenberger.Bd -literal -offset indent 287d19613acSJoerg Sonnenbergerfor (np = SPLAY_MIN(NAME, \*[Am]head); np != NULL; np = SPLAY_NEXT(NAME, \*[Am]head, np)) 288d19613acSJoerg Sonnenberger.Ed 289d19613acSJoerg Sonnenberger.Pp 290d19613acSJoerg SonnenbergerOr, for simplicity, one can use the 291d19613acSJoerg Sonnenberger.Fn SPLAY_FOREACH 292d19613acSJoerg Sonnenbergermacro: 293d19613acSJoerg Sonnenberger.Bd -literal -offset indent 294d19613acSJoerg SonnenbergerSPLAY_FOREACH(np, NAME, head) 295d19613acSJoerg Sonnenberger.Ed 296d19613acSJoerg Sonnenberger.Pp 297d19613acSJoerg SonnenbergerThe 298d19613acSJoerg Sonnenberger.Fn SPLAY_EMPTY 299d19613acSJoerg Sonnenbergermacro should be used to check whether a splay tree is empty. 300d19613acSJoerg Sonnenberger.Sh RED-BLACK TREES 301d19613acSJoerg SonnenbergerA red-black tree is a binary search tree with the node color as an 302d19613acSJoerg Sonnenbergerextra attribute. 303d19613acSJoerg SonnenbergerIt fulfills a set of conditions: 304d19613acSJoerg Sonnenberger.Bl -enum -compact -offset indent 305d19613acSJoerg Sonnenberger.It 306d19613acSJoerg Sonnenbergerevery search path from the root to a leaf consists of the same number of 307d19613acSJoerg Sonnenbergerblack nodes, 308d19613acSJoerg Sonnenberger.It 309d19613acSJoerg Sonnenbergereach red node (except for the root) has a black parent, 310d19613acSJoerg Sonnenberger.It 311d19613acSJoerg Sonnenbergereach leaf node is black. 312d19613acSJoerg Sonnenberger.El 313d19613acSJoerg Sonnenberger.Pp 314d19613acSJoerg SonnenbergerEvery operation on a red-black tree is bounded as O(lg n). 315d19613acSJoerg SonnenbergerThe maximum height of a red-black tree is 2lg (n+1). 316d19613acSJoerg Sonnenberger.Pp 317d19613acSJoerg SonnenbergerA red-black tree is headed by a structure defined by the 318d19613acSJoerg Sonnenberger.Fn RB_HEAD 319d19613acSJoerg Sonnenbergermacro. 320d19613acSJoerg SonnenbergerA 321d19613acSJoerg Sonnenberger.Fa RB_HEAD 322d19613acSJoerg Sonnenbergerstructure is declared as follows: 323d19613acSJoerg Sonnenberger.Bd -literal -offset indent 324d19613acSJoerg SonnenbergerRB_HEAD(HEADNAME, TYPE) head; 325d19613acSJoerg Sonnenberger.Ed 326d19613acSJoerg Sonnenberger.Pp 327d19613acSJoerg Sonnenbergerwhere 328d19613acSJoerg Sonnenberger.Fa HEADNAME 329d19613acSJoerg Sonnenbergeris the name of the structure to be defined, and struct 330d19613acSJoerg Sonnenberger.Fa TYPE 331d19613acSJoerg Sonnenbergeris the type of the elements to be inserted into the tree. 332d19613acSJoerg Sonnenberger.Pp 333d19613acSJoerg SonnenbergerThe 334d19613acSJoerg Sonnenberger.Fn RB_ENTRY 335d19613acSJoerg Sonnenbergermacro declares a structure that allows elements to be connected in the tree. 336d19613acSJoerg Sonnenberger.Pp 337d19613acSJoerg SonnenbergerIn order to use the functions that manipulate the tree structure, 338d19613acSJoerg Sonnenbergertheir prototypes need to be declared with the 339d19613acSJoerg Sonnenberger.Fn RB_PROTOTYPE 340d19613acSJoerg Sonnenbergermacro, 341d19613acSJoerg Sonnenbergerwhere 342d19613acSJoerg Sonnenberger.Fa NAME 343d19613acSJoerg Sonnenbergeris a unique identifier for this particular tree. 344d19613acSJoerg SonnenbergerThe 345d19613acSJoerg Sonnenberger.Fa TYPE 346d19613acSJoerg Sonnenbergerargument is the type of the structure that is being managed 347d19613acSJoerg Sonnenbergerby the tree. 348d19613acSJoerg SonnenbergerThe 349d19613acSJoerg Sonnenberger.Fa FIELD 350d19613acSJoerg Sonnenbergerargument is the name of the element defined by 351d19613acSJoerg Sonnenberger.Fn RB_ENTRY . 352d19613acSJoerg Sonnenberger.Pp 353d19613acSJoerg SonnenbergerThe function bodies are generated with the 354d19613acSJoerg Sonnenberger.Fn RB_GENERATE 355d19613acSJoerg Sonnenbergermacro. 356d19613acSJoerg SonnenbergerIt takes the same arguments as the 357d19613acSJoerg Sonnenberger.Fn RB_PROTOTYPE 358d19613acSJoerg Sonnenbergermacro, but should be used only once. 359d19613acSJoerg Sonnenberger.Pp 360d19613acSJoerg SonnenbergerFinally, 361d19613acSJoerg Sonnenbergerthe 362d19613acSJoerg Sonnenberger.Fa CMP 363d19613acSJoerg Sonnenbergerargument is the name of a function used to compare trees noded 364d19613acSJoerg Sonnenbergerwith each other. 365d19613acSJoerg SonnenbergerThe function takes two arguments of type 366d19613acSJoerg Sonnenberger.Fa "struct TYPE *" . 367d19613acSJoerg SonnenbergerIf the first argument is smaller than the second, the function returns a 368d19613acSJoerg Sonnenbergervalue smaller than zero. 369d19613acSJoerg SonnenbergerIf they are equal, the function returns zero. 370d19613acSJoerg SonnenbergerOtherwise, it should return a value greater than zero. 371d19613acSJoerg SonnenbergerThe compare function defines the order of the tree elements. 372d19613acSJoerg Sonnenberger.Pp 373d19613acSJoerg SonnenbergerThe 374d19613acSJoerg Sonnenberger.Fn RB_INIT 375d19613acSJoerg Sonnenbergermacro initializes the tree referenced by 376d19613acSJoerg Sonnenberger.Fa head . 377d19613acSJoerg Sonnenberger.Pp 378d19613acSJoerg SonnenbergerThe redblack tree can also be initialized statically by using the 379d19613acSJoerg Sonnenberger.Fn RB_INITIALIZER 380d19613acSJoerg Sonnenbergermacro like this: 381d19613acSJoerg Sonnenberger.Bd -literal -offset indent 382d19613acSJoerg SonnenbergerRB_HEAD(HEADNAME, TYPE) head = RB_INITIALIZER(\*[Am]head); 383d19613acSJoerg Sonnenberger.Ed 384d19613acSJoerg Sonnenberger.Pp 385d19613acSJoerg SonnenbergerThe 386d19613acSJoerg Sonnenberger.Fn RB_INSERT 387d19613acSJoerg Sonnenbergermacro inserts the new element 388d19613acSJoerg Sonnenberger.Fa elm 389d19613acSJoerg Sonnenbergerinto the tree. 390d19613acSJoerg Sonnenberger.Pp 391d19613acSJoerg SonnenbergerThe 392d19613acSJoerg Sonnenberger.Fn RB_REMOVE 393d19613acSJoerg Sonnenbergermacro removes the element 394d19613acSJoerg Sonnenberger.Fa elm 395d19613acSJoerg Sonnenbergerfrom the tree pointed by 396d19613acSJoerg Sonnenberger.Fa head . 397d19613acSJoerg Sonnenberger.Pp 398d19613acSJoerg SonnenbergerThe 399d19613acSJoerg Sonnenberger.Fn RB_FIND 400d19613acSJoerg Sonnenbergermacro can be used to find a particular element in the tree. 401d19613acSJoerg Sonnenberger.Bd -literal -offset indent 402d19613acSJoerg Sonnenbergerstruct TYPE find, *res; 403d19613acSJoerg Sonnenbergerfind.key = 30; 404d19613acSJoerg Sonnenbergerres = RB_FIND(NAME, head, \*[Am]find); 405d19613acSJoerg Sonnenberger.Ed 406d19613acSJoerg Sonnenberger.Pp 407d19613acSJoerg SonnenbergerThe 408d19613acSJoerg Sonnenberger.Fn RB_ROOT , 409d19613acSJoerg Sonnenberger.Fn RB_MIN , 410d19613acSJoerg Sonnenberger.Fn RB_MAX , 411d19613acSJoerg Sonnenbergerand 412d19613acSJoerg Sonnenberger.Fn RB_NEXT 413d19613acSJoerg Sonnenbergermacros can be used to traverse the tree: 414d19613acSJoerg Sonnenberger.Bd -literal -offset indent 415d19613acSJoerg Sonnenbergerfor (np = RB_MIN(NAME, \*[Am]head); np != NULL; np = RB_NEXT(NAME, \*[Am]head, np)) 416d19613acSJoerg Sonnenberger.Ed 417d19613acSJoerg Sonnenberger.Pp 418d19613acSJoerg SonnenbergerOr, for simplicity, one can use the 419d19613acSJoerg Sonnenberger.Fn RB_FOREACH 420*37149c60SSascha Wildneror 421*37149c60SSascha Wildner.Fn RB_FOREACH_REVERSE 422d19613acSJoerg Sonnenbergermacro: 423d19613acSJoerg Sonnenberger.Bd -literal -offset indent 424d19613acSJoerg SonnenbergerRB_FOREACH(np, NAME, head) 425d19613acSJoerg Sonnenberger.Ed 426d19613acSJoerg Sonnenberger.Pp 427*37149c60SSascha WildnerThe macros 428*37149c60SSascha Wildner.Fn RB_FOREACH_SAFE 429*37149c60SSascha Wildnerand 430*37149c60SSascha Wildner.Fn RB_FOREACH_REVERSE_SAFE 431*37149c60SSascha Wildnertraverse the tree referenced by head 432*37149c60SSascha Wildnerin a forward or reverse direction respectively, 433*37149c60SSascha Wildnerassigning each element in turn to np. 434*37149c60SSascha WildnerHowever, unlike their unsafe counterparts, 435*37149c60SSascha Wildnerthey permit both the removal of np 436*37149c60SSascha Wildneras well as freeing it from within the loop safely 437*37149c60SSascha Wildnerwithout interfering with the traversal. 438*37149c60SSascha Wildner.Pp 439*37149c60SSascha WildnerBoth 440*37149c60SSascha Wildner.Fn RB_FOREACH_FROM 441*37149c60SSascha Wildnerand 442*37149c60SSascha Wildner.Fn RB_FOREACH_REVERSE_FROM 443*37149c60SSascha Wildnermay be used to continue an interrupted traversal 444*37149c60SSascha Wildnerin a forward or reverse direction respectively. 445*37149c60SSascha WildnerThe head pointer is not required. 446*37149c60SSascha WildnerThe pointer to the node from where to resume the traversal 447*37149c60SSascha Wildnershould be passed as their last argument, 448*37149c60SSascha Wildnerand will be overwritten to provide safe traversal. 449*37149c60SSascha Wildner.Pp 450d19613acSJoerg SonnenbergerThe 451d19613acSJoerg Sonnenberger.Fn RB_EMPTY 452d19613acSJoerg Sonnenbergermacro should be used to check whether a red-black tree is empty. 453d19613acSJoerg Sonnenberger.Sh NOTES 454d19613acSJoerg SonnenbergerTrying to free a tree in the following way is a common error: 455d19613acSJoerg Sonnenberger.Bd -literal -offset indent 456d19613acSJoerg SonnenbergerSPLAY_FOREACH(var, NAME, head) { 457d19613acSJoerg Sonnenberger SPLAY_REMOVE(NAME, head, var); 458d19613acSJoerg Sonnenberger free(var); 459d19613acSJoerg Sonnenberger} 460d19613acSJoerg Sonnenbergerfree(head); 461d19613acSJoerg Sonnenberger.Ed 462d19613acSJoerg Sonnenberger.Pp 463d19613acSJoerg SonnenbergerSince 464d19613acSJoerg Sonnenberger.Va var 465d19613acSJoerg Sonnenbergeris free'd, the 466aeb4517eSSascha Wildner.Fn SPLAY_FOREACH 467d19613acSJoerg Sonnenbergermacro refers to a pointer that may have been reallocated already. 468d19613acSJoerg SonnenbergerProper code needs a second variable. 469d19613acSJoerg Sonnenberger.Bd -literal -offset indent 470d19613acSJoerg Sonnenbergerfor (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) { 471d19613acSJoerg Sonnenberger nxt = SPLAY_NEXT(NAME, head, var); 472d19613acSJoerg Sonnenberger SPLAY_REMOVE(NAME, head, var); 473d19613acSJoerg Sonnenberger free(var); 474d19613acSJoerg Sonnenberger} 475d19613acSJoerg Sonnenberger.Ed 476d19613acSJoerg Sonnenberger.Pp 477d19613acSJoerg SonnenbergerBoth 478d19613acSJoerg Sonnenberger.Fn RB_INSERT 479d19613acSJoerg Sonnenbergerand 480d19613acSJoerg Sonnenberger.Fn SPLAY_INSERT 481d19613acSJoerg Sonnenbergerreturn 482d19613acSJoerg Sonnenberger.Dv NULL 483d19613acSJoerg Sonnenbergerif the element was inserted in the tree successfully, otherwise they 484d19613acSJoerg Sonnenbergerreturn a pointer to the element with the colliding key. 485d19613acSJoerg Sonnenberger.Pp 486d19613acSJoerg SonnenbergerAccordingly, 487d19613acSJoerg Sonnenberger.Fn RB_REMOVE 488d19613acSJoerg Sonnenbergerand 489d19613acSJoerg Sonnenberger.Fn SPLAY_REMOVE 490d19613acSJoerg Sonnenbergerreturn the pointer to the removed element, otherwise they return 491d19613acSJoerg Sonnenberger.Dv NULL 492d19613acSJoerg Sonnenbergerto indicate an error. 493d19613acSJoerg Sonnenberger.Sh AUTHORS 494d19613acSJoerg SonnenbergerThe author of the tree macros is 495d19613acSJoerg Sonnenberger.An Niels Provos . 496