1*c21bbb21Sflorian.\" $OpenBSD: tree.3,v 1.30 2019/05/10 13:13:14 florian Exp $ 2c1d6f131Sprovos.\"/* 3c1d6f131Sprovos.\" * Copyright 2002 Niels Provos <provos@citi.umich.edu> 4c1d6f131Sprovos.\" * All rights reserved. 5c1d6f131Sprovos.\" * 6c1d6f131Sprovos.\" * Redistribution and use in source and binary forms, with or without 7c1d6f131Sprovos.\" * modification, are permitted provided that the following conditions 8c1d6f131Sprovos.\" * are met: 9c1d6f131Sprovos.\" * 1. Redistributions of source code must retain the above copyright 10c1d6f131Sprovos.\" * notice, this list of conditions and the following disclaimer. 11c1d6f131Sprovos.\" * 2. Redistributions in binary form must reproduce the above copyright 12c1d6f131Sprovos.\" * notice, this list of conditions and the following disclaimer in the 13c1d6f131Sprovos.\" * documentation and/or other materials provided with the distribution. 14c1d6f131Sprovos.\" * 15c1d6f131Sprovos.\" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16c1d6f131Sprovos.\" * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17c1d6f131Sprovos.\" * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18c1d6f131Sprovos.\" * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19c1d6f131Sprovos.\" * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20c1d6f131Sprovos.\" * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21c1d6f131Sprovos.\" * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22c1d6f131Sprovos.\" * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23c1d6f131Sprovos.\" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24c1d6f131Sprovos.\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25c1d6f131Sprovos.\" */ 26*c21bbb21Sflorian.Dd $Mdocdate: May 10 2019 $ 27d04ba2ccSjmc.Dt SPLAY_INIT 3 28c1d6f131Sprovos.Os 29c1d6f131Sprovos.Sh NAME 30c1d6f131Sprovos.Nm SPLAY_PROTOTYPE , 31c1d6f131Sprovos.Nm SPLAY_GENERATE , 32c1d6f131Sprovos.Nm SPLAY_ENTRY , 33c1d6f131Sprovos.Nm SPLAY_HEAD , 34743dcd30Sfrantzen.Nm SPLAY_INITIALIZER , 35c1d6f131Sprovos.Nm SPLAY_ROOT , 36743dcd30Sfrantzen.Nm SPLAY_EMPTY , 37c1d6f131Sprovos.Nm SPLAY_NEXT , 38c1d6f131Sprovos.Nm SPLAY_MIN , 39c1d6f131Sprovos.Nm SPLAY_MAX , 40c1d6f131Sprovos.Nm SPLAY_FIND , 41c1d6f131Sprovos.Nm SPLAY_LEFT , 42c1d6f131Sprovos.Nm SPLAY_RIGHT , 43c1d6f131Sprovos.Nm SPLAY_FOREACH , 44c1d6f131Sprovos.Nm SPLAY_INIT , 45c1d6f131Sprovos.Nm SPLAY_INSERT , 46c1d6f131Sprovos.Nm SPLAY_REMOVE , 47c1d6f131Sprovos.Nm RB_PROTOTYPE , 488dd272abSmillert.Nm RB_PROTOTYPE_STATIC , 49c1d6f131Sprovos.Nm RB_GENERATE , 508dd272abSmillert.Nm RB_GENERATE_STATIC , 51c1d6f131Sprovos.Nm RB_ENTRY , 52c1d6f131Sprovos.Nm RB_HEAD , 53743dcd30Sfrantzen.Nm RB_INITIALIZER , 54c1d6f131Sprovos.Nm RB_ROOT , 55743dcd30Sfrantzen.Nm RB_EMPTY , 56c1d6f131Sprovos.Nm RB_NEXT , 578dd272abSmillert.Nm RB_PREV , 58c1d6f131Sprovos.Nm RB_MIN , 59c1d6f131Sprovos.Nm RB_MAX , 60c1d6f131Sprovos.Nm RB_FIND , 618dd272abSmillert.Nm RB_NFIND , 62c1d6f131Sprovos.Nm RB_LEFT , 63c1d6f131Sprovos.Nm RB_RIGHT , 64c1d6f131Sprovos.Nm RB_PARENT , 65c1d6f131Sprovos.Nm RB_FOREACH , 662acff70eSpirofti.Nm RB_FOREACH_SAFE , 678dd272abSmillert.Nm RB_FOREACH_REVERSE , 682acff70eSpirofti.Nm RB_FOREACH_REVERSE_SAFE , 69c1d6f131Sprovos.Nm RB_INIT , 70c1d6f131Sprovos.Nm RB_INSERT , 71c1d6f131Sprovos.Nm RB_REMOVE 7273d4fc9bSjmc.Nd implementations of splay and red-black trees 73c1d6f131Sprovos.Sh SYNOPSIS 74cfcc6981Stedu.In sys/tree.h 75c1d6f131Sprovos.Pp 76c1d6f131Sprovos.Fn SPLAY_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" 77c1d6f131Sprovos.Fn SPLAY_GENERATE "NAME" "TYPE" "FIELD" "CMP" 78c1d6f131Sprovos.Fn SPLAY_ENTRY "TYPE" 79c1d6f131Sprovos.Fn SPLAY_HEAD "HEADNAME" "TYPE" 80c1d6f131Sprovos.Ft "struct TYPE *" 81743dcd30Sfrantzen.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head" 82c1d6f131Sprovos.Fn SPLAY_ROOT "SPLAY_HEAD *head" 839b994d6fSotto.Ft "int" 84743dcd30Sfrantzen.Fn SPLAY_EMPTY "SPLAY_HEAD *head" 85c1d6f131Sprovos.Ft "struct TYPE *" 86c1d6f131Sprovos.Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 87c1d6f131Sprovos.Ft "struct TYPE *" 88ce5c5d17Sdugsong.Fn SPLAY_MIN "NAME" "SPLAY_HEAD *head" 89c1d6f131Sprovos.Ft "struct TYPE *" 90ce5c5d17Sdugsong.Fn SPLAY_MAX "NAME" "SPLAY_HEAD *head" 91c1d6f131Sprovos.Ft "struct TYPE *" 92c1d6f131Sprovos.Fn SPLAY_FIND "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 93c1d6f131Sprovos.Ft "struct TYPE *" 94c1d6f131Sprovos.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME" 95c1d6f131Sprovos.Ft "struct TYPE *" 96c1d6f131Sprovos.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" 97c1d6f131Sprovos.Fn SPLAY_FOREACH "VARNAME" "NAME" "SPLAY_HEAD *head" 98c1d6f131Sprovos.Ft void 99c1d6f131Sprovos.Fn SPLAY_INIT "SPLAY_HEAD *head" 10048a22977Sprovos.Ft "struct TYPE *" 101c1d6f131Sprovos.Fn SPLAY_INSERT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 10248a22977Sprovos.Ft "struct TYPE *" 103c1d6f131Sprovos.Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 104c1d6f131Sprovos.Pp 105c1d6f131Sprovos.Fn RB_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" 1068dd272abSmillert.Fn RB_PROTOTYPE_STATIC "NAME" "TYPE" "FIELD" "CMP" 107c1d6f131Sprovos.Fn RB_GENERATE "NAME" "TYPE" "FIELD" "CMP" 1088dd272abSmillert.Fn RB_GENERATE_STATIC "NAME" "TYPE" "FIELD" "CMP" 109c1d6f131Sprovos.Fn RB_ENTRY "TYPE" 110c1d6f131Sprovos.Fn RB_HEAD "HEADNAME" "TYPE" 111743dcd30Sfrantzen.Fn RB_INITIALIZER "RB_HEAD *head" 112c1d6f131Sprovos.Ft "struct TYPE *" 113c1d6f131Sprovos.Fn RB_ROOT "RB_HEAD *head" 1149b994d6fSotto.Ft "int" 115743dcd30Sfrantzen.Fn RB_EMPTY "RB_HEAD *head" 116c1d6f131Sprovos.Ft "struct TYPE *" 117c1d6f131Sprovos.Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm" 118c1d6f131Sprovos.Ft "struct TYPE *" 1198dd272abSmillert.Fn RB_PREV "NAME" "RB_HEAD *head" "struct TYPE *elm" 1208dd272abSmillert.Ft "struct TYPE *" 121ce5c5d17Sdugsong.Fn RB_MIN "NAME" "RB_HEAD *head" 122c1d6f131Sprovos.Ft "struct TYPE *" 123ce5c5d17Sdugsong.Fn RB_MAX "NAME" "RB_HEAD *head" 124c1d6f131Sprovos.Ft "struct TYPE *" 125c1d6f131Sprovos.Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm" 126c1d6f131Sprovos.Ft "struct TYPE *" 1278dd272abSmillert.Fn RB_NFIND "NAME" "RB_HEAD *head" "struct TYPE *elm" 1288dd272abSmillert.Ft "struct TYPE *" 129c1d6f131Sprovos.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" 130c1d6f131Sprovos.Ft "struct TYPE *" 131c1d6f131Sprovos.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" 132c1d6f131Sprovos.Ft "struct TYPE *" 133c1d6f131Sprovos.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" 134c1d6f131Sprovos.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head" 1352acff70eSpirofti.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 1368dd272abSmillert.Fn RB_FOREACH_REVERSE "VARNAME" "NAME" "RB_HEAD *head" 1372acff70eSpirofti.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 138c1d6f131Sprovos.Ft void 139c1d6f131Sprovos.Fn RB_INIT "RB_HEAD *head" 14048a22977Sprovos.Ft "struct TYPE *" 141c1d6f131Sprovos.Fn RB_INSERT "NAME" "RB_HEAD *head" "struct TYPE *elm" 14248a22977Sprovos.Ft "struct TYPE *" 143c1d6f131Sprovos.Fn RB_REMOVE "NAME" "RB_HEAD *head" "struct TYPE *elm" 144c1d6f131Sprovos.Sh DESCRIPTION 145cc405d09SjmcThese macros define data structures for different types of trees: 146c1d6f131Sprovossplay trees and red-black trees. 147c1d6f131Sprovos.Pp 148c1d6f131SprovosIn the macro definitions, 149c1d6f131Sprovos.Fa TYPE 1505755dd49Sjmcis the name tag of a user defined structure that must contain a field named 1515755dd49Sjmc.Fa FIELD , 1525755dd49Sjmcof type 1535755dd49Sjmc.Li SPLAY_ENTRY 154c1d6f131Sprovosor 1555755dd49Sjmc.Li RB_ENTRY . 156c1d6f131SprovosThe argument 157c1d6f131Sprovos.Fa HEADNAME 158c1d6f131Sprovosis the name tag of a user defined structure that must be declared 159c1d6f131Sprovosusing the macros 160cc405d09Sjmc.Fn SPLAY_HEAD 161c1d6f131Sprovosor 162c1d6f131Sprovos.Fn RB_HEAD . 163c1d6f131SprovosThe argument 164c1d6f131Sprovos.Fa NAME 165c1d6f131Sprovoshas to be a unique name prefix for every tree that is defined. 166c1d6f131Sprovos.Pp 1678dd272abSmillertThe function prototypes are declared with 1688dd272abSmillert.Li SPLAY_PROTOTYPE , 1698dd272abSmillert.Li RB_PROTOTYPE , 170c1d6f131Sprovosor 1718dd272abSmillert.Li RB_PROTOTYPE_STATIC . 1728dd272abSmillertThe function bodies are generated with 1738dd272abSmillert.Li SPLAY_GENERATE , 1748dd272abSmillert.Li RB_GENERATE , 175c1d6f131Sprovosor 1768dd272abSmillert.Li RB_GENERATE_STATIC . 177c1d6f131SprovosSee the examples below for further explanation of how these macros are used. 178c1d6f131Sprovos.Sh SPLAY TREES 179954ddbd6SmpechA splay tree is a self-organizing data structure. 180954ddbd6SmpechEvery operation on the tree causes a splay to happen. 181954ddbd6SmpechThe splay moves the requested node to the root of the tree and partly 182954ddbd6Smpechrebalances it. 183c1d6f131Sprovos.Pp 184c1d6f131SprovosThis has the benefit that request locality causes faster lookups as 185954ddbd6Smpechthe requested nodes move to the top of the tree. 186954ddbd6SmpechOn the other hand, every lookup causes memory writes. 187c1d6f131Sprovos.Pp 188c1d6f131SprovosThe Balance Theorem bounds the total access time for m operations 189954ddbd6Smpechand n inserts on an initially empty tree as O((m + n)lg n). 190cc405d09SjmcThe amortized cost for a sequence of m accesses to a splay tree is O(lg n). 191c1d6f131Sprovos.Pp 192c1d6f131SprovosA splay tree is headed by a structure defined by the 193c1d6f131Sprovos.Fn SPLAY_HEAD 194c1d6f131Sprovosmacro. 195c1d6f131SprovosA 196c1d6f131Sprovos.Fa SPLAY_HEAD 197c1d6f131Sprovosstructure is declared as follows: 198c1d6f131Sprovos.Bd -literal -offset indent 199c1d6f131SprovosSPLAY_HEAD(HEADNAME, TYPE) head; 200c1d6f131Sprovos.Ed 201c1d6f131Sprovos.Pp 202c1d6f131Sprovoswhere 203c1d6f131Sprovos.Fa HEADNAME 204c1d6f131Sprovosis the name of the structure to be defined, and struct 205c1d6f131Sprovos.Fa TYPE 206c1d6f131Sprovosis the type of the elements to be inserted into the tree. 207c1d6f131Sprovos.Pp 208c1d6f131SprovosThe 209c1d6f131Sprovos.Fn SPLAY_ENTRY 210c1d6f131Sprovosmacro declares a structure that allows elements to be connected in the tree. 211c1d6f131Sprovos.Pp 212c1d6f131SprovosIn order to use the functions that manipulate the tree structure, 213c1d6f131Sprovostheir prototypes need to be declared with the 214c1d6f131Sprovos.Fn SPLAY_PROTOTYPE 215c1d6f131Sprovosmacro, 216c1d6f131Sprovoswhere 217c1d6f131Sprovos.Fa NAME 218c1d6f131Sprovosis a unique identifier for this particular tree. 219c1d6f131SprovosThe 220c1d6f131Sprovos.Fa TYPE 221c1d6f131Sprovosargument is the type of the structure that is being managed 222c1d6f131Sprovosby the tree. 223c1d6f131SprovosThe 224c1d6f131Sprovos.Fa FIELD 225c1d6f131Sprovosargument is the name of the element defined by 226c1d6f131Sprovos.Fn SPLAY_ENTRY . 227c1d6f131Sprovos.Pp 228c1d6f131SprovosThe function bodies are generated with the 229c1d6f131Sprovos.Fn SPLAY_GENERATE 230954ddbd6Smpechmacro. 231954ddbd6SmpechIt takes the same arguments as the 232c1d6f131Sprovos.Fn SPLAY_PROTOTYPE 233c1d6f131Sprovosmacro, but should be used only once. 234c1d6f131Sprovos.Pp 235c1d6f131SprovosFinally, 236c1d6f131Sprovosthe 237c1d6f131Sprovos.Fa CMP 2385755dd49Sjmcargument is the name of a function used to compare trees' nodes 239954ddbd6Smpechwith each other. 240954ddbd6SmpechThe function takes two arguments of type 241c1d6f131Sprovos.Fa "struct TYPE *" . 242c1d6f131SprovosIf the first argument is smaller than the second, the function returns a 243954ddbd6Smpechvalue smaller than zero. 244954ddbd6SmpechIf they are equal, the function returns zero. 245954ddbd6SmpechOtherwise, it should return a value greater than zero. 246954ddbd6SmpechThe compare function defines the order of the tree elements. 247c1d6f131Sprovos.Pp 248c1d6f131SprovosThe 249c1d6f131Sprovos.Fn SPLAY_INIT 250c1d6f131Sprovosmacro initializes the tree referenced by 251c1d6f131Sprovos.Fa head . 252c1d6f131Sprovos.Pp 253743dcd30SfrantzenThe splay tree can also be initialized statically by using the 254743dcd30Sfrantzen.Fn SPLAY_INITIALIZER 255743dcd30Sfrantzenmacro like this: 256743dcd30Sfrantzen.Bd -literal -offset indent 257743dcd30SfrantzenSPLAY_HEAD(HEADNAME, TYPE) head = SPLAY_INITIALIZER(&head); 258743dcd30Sfrantzen.Ed 259743dcd30Sfrantzen.Pp 260c1d6f131SprovosThe 261c1d6f131Sprovos.Fn SPLAY_INSERT 262c1d6f131Sprovosmacro inserts the new element 263c1d6f131Sprovos.Fa elm 264c1d6f131Sprovosinto the tree. 26524c16576SnicmUpon success, 26624c16576Snicm.Va NULL 26724c16576Snicmis returned. 26824c16576SnicmIf a matching element already exists in the tree, the insertion is 26924c16576Snicmaborted, and a pointer to the existing element is returned. 270c1d6f131Sprovos.Pp 271c1d6f131SprovosThe 272c1d6f131Sprovos.Fn SPLAY_REMOVE 273c1d6f131Sprovosmacro removes the element 274c1d6f131Sprovos.Fa elm 275c1d6f131Sprovosfrom the tree pointed by 276c1d6f131Sprovos.Fa head . 27724c16576SnicmUpon success, a pointer to the removed element is returned. 27824c16576Snicm.Va NULL 27924c16576Snicmis returned if 28024c16576Snicm.Fa elm 28124c16576Snicmis not present in the tree. 282c1d6f131Sprovos.Pp 283c1d6f131SprovosThe 284c1d6f131Sprovos.Fn SPLAY_FIND 285e9c841b4Svincentmacro can be used to find a particular element in the tree. 286c1d6f131Sprovos.Bd -literal -offset indent 287c1d6f131Sprovosstruct TYPE find, *res; 288c1d6f131Sprovosfind.key = 30; 2898536b4aeSjmcres = SPLAY_FIND(NAME, &head, &find); 290c1d6f131Sprovos.Ed 291c1d6f131Sprovos.Pp 292c1d6f131SprovosThe 293c1d6f131Sprovos.Fn SPLAY_ROOT , 294c1d6f131Sprovos.Fn SPLAY_MIN , 295c1d6f131Sprovos.Fn SPLAY_MAX , 296c1d6f131Sprovosand 297c1d6f131Sprovos.Fn SPLAY_NEXT 298c1d6f131Sprovosmacros can be used to traverse the tree: 299c1d6f131Sprovos.Bd -literal -offset indent 300c1d6f131Sprovosfor (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np)) 301c1d6f131Sprovos.Ed 302c1d6f131Sprovos.Pp 303c1d6f131SprovosOr, for simplicity, one can use the 304c1d6f131Sprovos.Fn SPLAY_FOREACH 305c1d6f131Sprovosmacro: 306c1d6f131Sprovos.Bd -literal -offset indent 3078536b4aeSjmcSPLAY_FOREACH(np, NAME, &head) 308c1d6f131Sprovos.Ed 309c1d6f131Sprovos.Pp 310743dcd30SfrantzenThe 311743dcd30Sfrantzen.Fn SPLAY_EMPTY 312743dcd30Sfrantzenmacro should be used to check whether a splay tree is empty. 313c1d6f131Sprovos.Sh RED-BLACK TREES 314c1d6f131SprovosA red-black tree is a binary search tree with the node color as an 315954ddbd6Smpechextra attribute. 316954ddbd6SmpechIt fulfills a set of conditions: 3178536b4aeSjmc.Pp 318c1d6f131Sprovos.Bl -enum -compact -offset indent 319c1d6f131Sprovos.It 320c1d6f131Sprovosevery search path from the root to a leaf consists of the same number of 321c1d6f131Sprovosblack nodes, 322c1d6f131Sprovos.It 323c1d6f131Sprovoseach red node (except for the root) has a black parent, 324c1d6f131Sprovos.It 325c1d6f131Sprovoseach leaf node is black. 326c1d6f131Sprovos.El 327c1d6f131Sprovos.Pp 328c1d6f131SprovosEvery operation on a red-black tree is bounded as O(lg n). 329c1d6f131SprovosThe maximum height of a red-black tree is 2lg (n+1). 330c1d6f131Sprovos.Pp 331c1d6f131SprovosA red-black tree is headed by a structure defined by the 332c1d6f131Sprovos.Fn RB_HEAD 333c1d6f131Sprovosmacro. 334c1d6f131SprovosA 335c1d6f131Sprovos.Fa RB_HEAD 336c1d6f131Sprovosstructure is declared as follows: 337c1d6f131Sprovos.Bd -literal -offset indent 338c1d6f131SprovosRB_HEAD(HEADNAME, TYPE) head; 339c1d6f131Sprovos.Ed 340c1d6f131Sprovos.Pp 341c1d6f131Sprovoswhere 342c1d6f131Sprovos.Fa HEADNAME 343c1d6f131Sprovosis the name of the structure to be defined, and struct 344c1d6f131Sprovos.Fa TYPE 345c1d6f131Sprovosis the type of the elements to be inserted into the tree. 346c1d6f131Sprovos.Pp 347c1d6f131SprovosThe 348c1d6f131Sprovos.Fn RB_ENTRY 349c1d6f131Sprovosmacro declares a structure that allows elements to be connected in the tree. 350c1d6f131Sprovos.Pp 351c1d6f131SprovosIn order to use the functions that manipulate the tree structure, 352c1d6f131Sprovostheir prototypes need to be declared with the 353c1d6f131Sprovos.Fn RB_PROTOTYPE 3548dd272abSmillertor 3558dd272abSmillert.Fn RB_PROTOTYPE_STATIC 3568dd272abSmillertmacros, 357c1d6f131Sprovoswhere 358c1d6f131Sprovos.Fa NAME 359c1d6f131Sprovosis a unique identifier for this particular tree. 360c1d6f131SprovosThe 361c1d6f131Sprovos.Fa TYPE 362c1d6f131Sprovosargument is the type of the structure that is being managed 363c1d6f131Sprovosby the tree. 364c1d6f131SprovosThe 365c1d6f131Sprovos.Fa FIELD 366c1d6f131Sprovosargument is the name of the element defined by 367c1d6f131Sprovos.Fn RB_ENTRY . 368c1d6f131Sprovos.Pp 369c1d6f131SprovosThe function bodies are generated with the 370c1d6f131Sprovos.Fn RB_GENERATE 3718dd272abSmillertor 3728dd272abSmillert.Fn RB_GENERATE_STATIC 3738dd272abSmillertmacros. 3748dd272abSmillertThese macros take the same arguments as the 375c1d6f131Sprovos.Fn RB_PROTOTYPE 3768dd272abSmillertand 3778dd272abSmillert.Fn RB_PROTOTYPE_STATIC 3788dd272abSmillertmacros, but should be used only once. 379c1d6f131Sprovos.Pp 380c1d6f131SprovosFinally, 381c1d6f131Sprovosthe 382c1d6f131Sprovos.Fa CMP 3835755dd49Sjmcargument is the name of a function used to compare trees' nodes 384954ddbd6Smpechwith each other. 385954ddbd6SmpechThe function takes two arguments of type 386c1d6f131Sprovos.Fa "struct TYPE *" . 387c1d6f131SprovosIf the first argument is smaller than the second, the function returns a 388954ddbd6Smpechvalue smaller than zero. 389954ddbd6SmpechIf they are equal, the function returns zero. 390954ddbd6SmpechOtherwise, it should return a value greater than zero. 391954ddbd6SmpechThe compare function defines the order of the tree elements. 392c1d6f131Sprovos.Pp 393c1d6f131SprovosThe 394c1d6f131Sprovos.Fn RB_INIT 395c1d6f131Sprovosmacro initializes the tree referenced by 396c1d6f131Sprovos.Fa head . 397c1d6f131Sprovos.Pp 398374a343cSjmcThe red-black tree can also be initialized statically by using the 399743dcd30Sfrantzen.Fn RB_INITIALIZER 400743dcd30Sfrantzenmacro like this: 401743dcd30Sfrantzen.Bd -literal -offset indent 402743dcd30SfrantzenRB_HEAD(HEADNAME, TYPE) head = RB_INITIALIZER(&head); 403743dcd30Sfrantzen.Ed 404743dcd30Sfrantzen.Pp 405c1d6f131SprovosThe 406c1d6f131Sprovos.Fn RB_INSERT 407c1d6f131Sprovosmacro inserts the new element 408c1d6f131Sprovos.Fa elm 409c1d6f131Sprovosinto the tree. 410a21f5b4eSstspUpon success, 411a21f5b4eSstsp.Va NULL 412a21f5b4eSstspis returned. 413a21f5b4eSstspIf a matching element already exists in the tree, the insertion is 414a21f5b4eSstspaborted, and a pointer to the existing element is returned. 415c1d6f131Sprovos.Pp 416c1d6f131SprovosThe 417c1d6f131Sprovos.Fn RB_REMOVE 418c1d6f131Sprovosmacro removes the element 419c1d6f131Sprovos.Fa elm 420c1d6f131Sprovosfrom the tree pointed by 421c1d6f131Sprovos.Fa head . 42224c16576Snicm.Fn RB_REMOVE 42324c16576Snicmreturns 42424c16576Snicm.Fa elm . 425c1d6f131Sprovos.Pp 426c1d6f131SprovosThe 427c1d6f131Sprovos.Fn RB_FIND 4288dd272abSmillertand 4298dd272abSmillert.Fn RB_NFIND 4308dd272abSmillertmacros can be used to find a particular element in the tree. 4312d7ed59bSstsp.Fn RB_FIND 4322d7ed59bSstspfinds the node with the same key as 4332d7ed59bSstsp.Fa elm . 4342d7ed59bSstsp.Fn RB_NFIND 4352d7ed59bSstspfinds the first node greater than or equal to the search key. 436c1d6f131Sprovos.Bd -literal -offset indent 437c1d6f131Sprovosstruct TYPE find, *res; 438c1d6f131Sprovosfind.key = 30; 4398536b4aeSjmcres = RB_FIND(NAME, &head, &find); 440c1d6f131Sprovos.Ed 441c1d6f131Sprovos.Pp 442c1d6f131SprovosThe 443c1d6f131Sprovos.Fn RB_ROOT , 444c1d6f131Sprovos.Fn RB_MIN , 445c1d6f131Sprovos.Fn RB_MAX , 4468dd272abSmillert.Fn RB_NEXT , 447c1d6f131Sprovosand 4488dd272abSmillert.Fn RB_PREV 449c1d6f131Sprovosmacros can be used to traverse the tree: 450c1d6f131Sprovos.Bd -literal -offset indent 451c1d6f131Sprovosfor (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np)) 452c1d6f131Sprovos.Ed 453c1d6f131Sprovos.Pp 454c1d6f131SprovosOr, for simplicity, one can use the 455c1d6f131Sprovos.Fn RB_FOREACH 4568dd272abSmillertor 4578dd272abSmillert.Fn RB_FOREACH_REVERSE 4588dd272abSmillertmacros: 459c1d6f131Sprovos.Bd -literal -offset indent 4608536b4aeSjmcRB_FOREACH(np, NAME, &head) 461c1d6f131Sprovos.Ed 462c1d6f131Sprovos.Pp 463d2ad55b1SjmcThe macros 464d2ad55b1Sjmc.Fn RB_FOREACH_SAFE 465d2ad55b1Sjmcand 466d2ad55b1Sjmc.Fn RB_FOREACH_REVERSE_SAFE 467d2ad55b1Sjmctraverse the tree referenced by head 468d2ad55b1Sjmcin a forward or reverse direction respectively, 469d2ad55b1Sjmcassigning each element in turn to np. 470d2ad55b1SjmcHowever, unlike their unsafe counterparts, 471d2ad55b1Sjmcthey permit both the removal of np 472d2ad55b1Sjmcas well as freeing it from within the loop safely 473d2ad55b1Sjmcwithout interfering with the traversal. 4742acff70eSpirofti.Pp 475743dcd30SfrantzenThe 476743dcd30Sfrantzen.Fn RB_EMPTY 477374a343cSjmcmacro should be used to check whether a red-black tree is empty. 478bc636980Sotto.Sh EXAMPLES 479bc636980SottoThe following example demonstrates how to declare a red-black tree 480bc636980Sottoholding integers. 481bc636980SottoValues are inserted into it and the contents of the tree are printed 482bc636980Sottoin order. 483bc636980SottoLastly, the internal structure of the tree is printed. 484bc636980Sotto.Bd -literal -offset 3n 485bc636980Sotto#include <sys/tree.h> 486bc636980Sotto#include <err.h> 487bc636980Sotto#include <stdio.h> 488bc636980Sotto#include <stdlib.h> 489bc636980Sotto 490bc636980Sottostruct node { 491bc636980Sotto RB_ENTRY(node) entry; 492bc636980Sotto int i; 493bc636980Sotto}; 494bc636980Sotto 495*c21bbb21Sflorianint intcmp(struct node *, struct node *); 496*c21bbb21Sflorianvoid print_tree(struct node *); 497*c21bbb21Sflorian 498bc636980Sottoint 499bc636980Sottointcmp(struct node *e1, struct node *e2) 500bc636980Sotto{ 501eea53342Stedu return (e1->i < e2->i ? -1 : e1->i > e2->i); 502bc636980Sotto} 503bc636980Sotto 504bc636980SottoRB_HEAD(inttree, node) head = RB_INITIALIZER(&head); 505*c21bbb21SflorianRB_PROTOTYPE(inttree, node, entry, intcmp) 506bc636980SottoRB_GENERATE(inttree, node, entry, intcmp) 507bc636980Sotto 508bc636980Sottoint testdata[] = { 509bc636980Sotto 20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18, 510bc636980Sotto 7, 11, 14 511bc636980Sotto}; 512bc636980Sotto 513bc636980Sottovoid 514bc636980Sottoprint_tree(struct node *n) 515bc636980Sotto{ 516bc636980Sotto struct node *left, *right; 517bc636980Sotto 518bc636980Sotto if (n == NULL) { 519bc636980Sotto printf("nil"); 520bc636980Sotto return; 521bc636980Sotto } 522bc636980Sotto left = RB_LEFT(n, entry); 523bc636980Sotto right = RB_RIGHT(n, entry); 524bc636980Sotto if (left == NULL && right == NULL) 525bc636980Sotto printf("%d", n->i); 526bc636980Sotto else { 527bc636980Sotto printf("%d(", n->i); 528bc636980Sotto print_tree(left); 529bc636980Sotto printf(","); 530bc636980Sotto print_tree(right); 531bc636980Sotto printf(")"); 532bc636980Sotto } 533bc636980Sotto} 534bc636980Sotto 535bc636980Sottoint 53654370b24Sjcamain(void) 537bc636980Sotto{ 538bc636980Sotto int i; 539bc636980Sotto struct node *n; 540bc636980Sotto 541bc636980Sotto for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) { 542bc636980Sotto if ((n = malloc(sizeof(struct node))) == NULL) 543bc636980Sotto err(1, NULL); 544bc636980Sotto n->i = testdata[i]; 545bc636980Sotto RB_INSERT(inttree, &head, n); 546bc636980Sotto } 547bc636980Sotto 548bc636980Sotto RB_FOREACH(n, inttree, &head) { 549bc636980Sotto printf("%d\en", n->i); 550bc636980Sotto } 551bc636980Sotto print_tree(RB_ROOT(&head)); 552bc636980Sotto printf("\en"); 553bc636980Sotto return (0); 554bc636980Sotto} 555bc636980Sotto.Ed 556b9af1e79Sjmc.Sh SEE ALSO 557b9af1e79Sjmc.Xr queue 3 558c1d6f131Sprovos.Sh NOTES 559c1d6f131SprovosTrying to free a tree in the following way is a common error: 560c1d6f131Sprovos.Bd -literal -offset indent 5618536b4aeSjmcSPLAY_FOREACH(var, NAME, &head) { 5628536b4aeSjmc SPLAY_REMOVE(NAME, &head, var); 563c1d6f131Sprovos free(var); 564aade6be7Sprovos} 565c1d6f131Sprovosfree(head); 566c1d6f131Sprovos.Ed 567c1d6f131Sprovos.Pp 568c1d6f131SprovosSince 569c1d6f131Sprovos.Va var 570c1d6f131Sprovosis free'd, the 571c1d6f131Sprovos.Fn FOREACH 572c1d6f131Sprovosmacro refers to a pointer that may have been reallocated already. 573c1d6f131SprovosProper code needs a second variable. 574c1d6f131Sprovos.Bd -literal -offset indent 5758536b4aeSjmcfor (var = SPLAY_MIN(NAME, &head); var != NULL; var = nxt) { 5768536b4aeSjmc nxt = SPLAY_NEXT(NAME, &head, var); 5778536b4aeSjmc SPLAY_REMOVE(NAME, &head, var); 578c1d6f131Sprovos free(var); 579c1d6f131Sprovos} 580c1d6f131Sprovos.Ed 581c1d6f131Sprovos.Sh AUTHORS 58227e95970SschwarzeThe author of the tree macros is 58327e95970Sschwarze.An Niels Provos . 584