1.\" $OpenBSD: tree.3,v 1.21 2010/05/05 18:17:41 nicm Exp $ 2.\"/* 3.\" * Copyright 2002 Niels Provos <provos@citi.umich.edu> 4.\" * All rights reserved. 5.\" * 6.\" * Redistribution and use in source and binary forms, with or without 7.\" * modification, are permitted provided that the following conditions 8.\" * are met: 9.\" * 1. Redistributions of source code must retain the above copyright 10.\" * notice, this list of conditions and the following disclaimer. 11.\" * 2. Redistributions in binary form must reproduce the above copyright 12.\" * notice, this list of conditions and the following disclaimer in the 13.\" * documentation and/or other materials provided with the distribution. 14.\" * 15.\" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16.\" * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17.\" * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18.\" * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19.\" * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20.\" * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21.\" * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22.\" * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23.\" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24.\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25.\" */ 26.Dd $Mdocdate: May 5 2010 $ 27.Dt TREE 3 28.Os 29.Sh NAME 30.Nm SPLAY_PROTOTYPE , 31.Nm SPLAY_GENERATE , 32.Nm SPLAY_ENTRY , 33.Nm SPLAY_HEAD , 34.Nm SPLAY_INITIALIZER , 35.Nm SPLAY_ROOT , 36.Nm SPLAY_EMPTY , 37.Nm SPLAY_NEXT , 38.Nm SPLAY_MIN , 39.Nm SPLAY_MAX , 40.Nm SPLAY_FIND , 41.Nm SPLAY_LEFT , 42.Nm SPLAY_RIGHT , 43.Nm SPLAY_FOREACH , 44.Nm SPLAY_INIT , 45.Nm SPLAY_INSERT , 46.Nm SPLAY_REMOVE , 47.Nm RB_PROTOTYPE , 48.Nm RB_PROTOTYPE_STATIC , 49.Nm RB_GENERATE , 50.Nm RB_GENERATE_STATIC , 51.Nm RB_ENTRY , 52.Nm RB_HEAD , 53.Nm RB_INITIALIZER , 54.Nm RB_ROOT , 55.Nm RB_EMPTY , 56.Nm RB_NEXT , 57.Nm RB_PREV , 58.Nm RB_MIN , 59.Nm RB_MAX , 60.Nm RB_FIND , 61.Nm RB_NFIND , 62.Nm RB_LEFT , 63.Nm RB_RIGHT , 64.Nm RB_PARENT , 65.Nm RB_FOREACH , 66.Nm RB_FOREACH_REVERSE , 67.Nm RB_INIT , 68.Nm RB_INSERT , 69.Nm RB_REMOVE 70.Nd "implementations of splay and red-black trees" 71.Sh SYNOPSIS 72.Fd #include <sys/tree.h> 73.Pp 74.Fn SPLAY_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" 75.Fn SPLAY_GENERATE "NAME" "TYPE" "FIELD" "CMP" 76.Fn SPLAY_ENTRY "TYPE" 77.Fn SPLAY_HEAD "HEADNAME" "TYPE" 78.Ft "struct TYPE *" 79.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head" 80.Fn SPLAY_ROOT "SPLAY_HEAD *head" 81.Ft "int" 82.Fn SPLAY_EMPTY "SPLAY_HEAD *head" 83.Ft "struct TYPE *" 84.Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 85.Ft "struct TYPE *" 86.Fn SPLAY_MIN "NAME" "SPLAY_HEAD *head" 87.Ft "struct TYPE *" 88.Fn SPLAY_MAX "NAME" "SPLAY_HEAD *head" 89.Ft "struct TYPE *" 90.Fn SPLAY_FIND "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 91.Ft "struct TYPE *" 92.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME" 93.Ft "struct TYPE *" 94.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" 95.Fn SPLAY_FOREACH "VARNAME" "NAME" "SPLAY_HEAD *head" 96.Ft void 97.Fn SPLAY_INIT "SPLAY_HEAD *head" 98.Ft "struct TYPE *" 99.Fn SPLAY_INSERT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 100.Ft "struct TYPE *" 101.Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 102.Pp 103.Fn RB_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" 104.Fn RB_PROTOTYPE_STATIC "NAME" "TYPE" "FIELD" "CMP" 105.Fn RB_GENERATE "NAME" "TYPE" "FIELD" "CMP" 106.Fn RB_GENERATE_STATIC "NAME" "TYPE" "FIELD" "CMP" 107.Fn RB_ENTRY "TYPE" 108.Fn RB_HEAD "HEADNAME" "TYPE" 109.Fn RB_INITIALIZER "RB_HEAD *head" 110.Ft "struct TYPE *" 111.Fn RB_ROOT "RB_HEAD *head" 112.Ft "int" 113.Fn RB_EMPTY "RB_HEAD *head" 114.Ft "struct TYPE *" 115.Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm" 116.Ft "struct TYPE *" 117.Fn RB_PREV "NAME" "RB_HEAD *head" "struct TYPE *elm" 118.Ft "struct TYPE *" 119.Fn RB_MIN "NAME" "RB_HEAD *head" 120.Ft "struct TYPE *" 121.Fn RB_MAX "NAME" "RB_HEAD *head" 122.Ft "struct TYPE *" 123.Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm" 124.Ft "struct TYPE *" 125.Fn RB_NFIND "NAME" "RB_HEAD *head" "struct TYPE *elm" 126.Ft "struct TYPE *" 127.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" 128.Ft "struct TYPE *" 129.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" 130.Ft "struct TYPE *" 131.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" 132.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head" 133.Fn RB_FOREACH_REVERSE "VARNAME" "NAME" "RB_HEAD *head" 134.Ft void 135.Fn RB_INIT "RB_HEAD *head" 136.Ft "struct TYPE *" 137.Fn RB_INSERT "NAME" "RB_HEAD *head" "struct TYPE *elm" 138.Ft "struct TYPE *" 139.Fn RB_REMOVE "NAME" "RB_HEAD *head" "struct TYPE *elm" 140.Sh DESCRIPTION 141These macros define data structures for different types of trees: 142splay trees and red-black trees. 143.Pp 144In the macro definitions, 145.Fa TYPE 146is the name tag of a user defined structure that must contain a field named 147.Fa FIELD , 148of type 149.Li SPLAY_ENTRY 150or 151.Li RB_ENTRY . 152The argument 153.Fa HEADNAME 154is the name tag of a user defined structure that must be declared 155using the macros 156.Fn SPLAY_HEAD 157or 158.Fn RB_HEAD . 159The argument 160.Fa NAME 161has to be a unique name prefix for every tree that is defined. 162.Pp 163The function prototypes are declared with 164.Li SPLAY_PROTOTYPE , 165.Li RB_PROTOTYPE , 166or 167.Li RB_PROTOTYPE_STATIC . 168The function bodies are generated with 169.Li SPLAY_GENERATE , 170.Li RB_GENERATE , 171or 172.Li RB_GENERATE_STATIC . 173See the examples below for further explanation of how these macros are used. 174.Sh SPLAY TREES 175A splay tree is a self-organizing data structure. 176Every operation on the tree causes a splay to happen. 177The splay moves the requested node to the root of the tree and partly 178rebalances it. 179.Pp 180This has the benefit that request locality causes faster lookups as 181the requested nodes move to the top of the tree. 182On the other hand, every lookup causes memory writes. 183.Pp 184The Balance Theorem bounds the total access time for m operations 185and n inserts on an initially empty tree as O((m + n)lg n). 186The amortized cost for a sequence of m accesses to a splay tree is O(lg n). 187.Pp 188A splay tree is headed by a structure defined by the 189.Fn SPLAY_HEAD 190macro. 191A 192.Fa SPLAY_HEAD 193structure is declared as follows: 194.Bd -literal -offset indent 195SPLAY_HEAD(HEADNAME, TYPE) head; 196.Ed 197.Pp 198where 199.Fa HEADNAME 200is the name of the structure to be defined, and struct 201.Fa TYPE 202is the type of the elements to be inserted into the tree. 203.Pp 204The 205.Fn SPLAY_ENTRY 206macro declares a structure that allows elements to be connected in the tree. 207.Pp 208In order to use the functions that manipulate the tree structure, 209their prototypes need to be declared with the 210.Fn SPLAY_PROTOTYPE 211macro, 212where 213.Fa NAME 214is a unique identifier for this particular tree. 215The 216.Fa TYPE 217argument is the type of the structure that is being managed 218by the tree. 219The 220.Fa FIELD 221argument is the name of the element defined by 222.Fn SPLAY_ENTRY . 223.Pp 224The function bodies are generated with the 225.Fn SPLAY_GENERATE 226macro. 227It takes the same arguments as the 228.Fn SPLAY_PROTOTYPE 229macro, but should be used only once. 230.Pp 231Finally, 232the 233.Fa CMP 234argument is the name of a function used to compare trees' nodes 235with each other. 236The function takes two arguments of type 237.Fa "struct TYPE *" . 238If the first argument is smaller than the second, the function returns a 239value smaller than zero. 240If they are equal, the function returns zero. 241Otherwise, it should return a value greater than zero. 242The compare function defines the order of the tree elements. 243.Pp 244The 245.Fn SPLAY_INIT 246macro initializes the tree referenced by 247.Fa head . 248.Pp 249The splay tree can also be initialized statically by using the 250.Fn SPLAY_INITIALIZER 251macro like this: 252.Bd -literal -offset indent 253SPLAY_HEAD(HEADNAME, TYPE) head = SPLAY_INITIALIZER(&head); 254.Ed 255.Pp 256The 257.Fn SPLAY_INSERT 258macro inserts the new element 259.Fa elm 260into the tree. 261Upon success, 262.Va NULL 263is returned. 264If a matching element already exists in the tree, the insertion is 265aborted, and a pointer to the existing element is returned. 266.Pp 267The 268.Fn SPLAY_REMOVE 269macro removes the element 270.Fa elm 271from the tree pointed by 272.Fa head . 273Upon success, a pointer to the removed element is returned. 274.Va NULL 275is returned if 276.Fa elm 277is not present in the tree. 278.Pp 279The 280.Fn SPLAY_FIND 281macro can be used to find a particular element in the tree. 282.Bd -literal -offset indent 283struct TYPE find, *res; 284find.key = 30; 285res = SPLAY_FIND(NAME, &head, &find); 286.Ed 287.Pp 288The 289.Fn SPLAY_ROOT , 290.Fn SPLAY_MIN , 291.Fn SPLAY_MAX , 292and 293.Fn SPLAY_NEXT 294macros can be used to traverse the tree: 295.Bd -literal -offset indent 296for (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np)) 297.Ed 298.Pp 299Or, for simplicity, one can use the 300.Fn SPLAY_FOREACH 301macro: 302.Bd -literal -offset indent 303SPLAY_FOREACH(np, NAME, &head) 304.Ed 305.Pp 306The 307.Fn SPLAY_EMPTY 308macro should be used to check whether a splay tree is empty. 309.Sh RED-BLACK TREES 310A red-black tree is a binary search tree with the node color as an 311extra attribute. 312It fulfills a set of conditions: 313.Pp 314.Bl -enum -compact -offset indent 315.It 316every search path from the root to a leaf consists of the same number of 317black nodes, 318.It 319each red node (except for the root) has a black parent, 320.It 321each leaf node is black. 322.El 323.Pp 324Every operation on a red-black tree is bounded as O(lg n). 325The maximum height of a red-black tree is 2lg (n+1). 326.Pp 327A red-black tree is headed by a structure defined by the 328.Fn RB_HEAD 329macro. 330A 331.Fa RB_HEAD 332structure is declared as follows: 333.Bd -literal -offset indent 334RB_HEAD(HEADNAME, TYPE) head; 335.Ed 336.Pp 337where 338.Fa HEADNAME 339is the name of the structure to be defined, and struct 340.Fa TYPE 341is the type of the elements to be inserted into the tree. 342.Pp 343The 344.Fn RB_ENTRY 345macro declares a structure that allows elements to be connected in the tree. 346.Pp 347In order to use the functions that manipulate the tree structure, 348their prototypes need to be declared with the 349.Fn RB_PROTOTYPE 350or 351.Fn RB_PROTOTYPE_STATIC 352macros, 353where 354.Fa NAME 355is a unique identifier for this particular tree. 356The 357.Fa TYPE 358argument is the type of the structure that is being managed 359by the tree. 360The 361.Fa FIELD 362argument is the name of the element defined by 363.Fn RB_ENTRY . 364.Pp 365The function bodies are generated with the 366.Fn RB_GENERATE 367or 368.Fn RB_GENERATE_STATIC 369macros. 370These macros take the same arguments as the 371.Fn RB_PROTOTYPE 372and 373.Fn RB_PROTOTYPE_STATIC 374macros, but should be used only once. 375.Pp 376Finally, 377the 378.Fa CMP 379argument is the name of a function used to compare trees' nodes 380with each other. 381The function takes two arguments of type 382.Fa "struct TYPE *" . 383If the first argument is smaller than the second, the function returns a 384value smaller than zero. 385If they are equal, the function returns zero. 386Otherwise, it should return a value greater than zero. 387The compare function defines the order of the tree elements. 388.Pp 389The 390.Fn RB_INIT 391macro initializes the tree referenced by 392.Fa head . 393.Pp 394The red-black tree can also be initialized statically by using the 395.Fn RB_INITIALIZER 396macro like this: 397.Bd -literal -offset indent 398RB_HEAD(HEADNAME, TYPE) head = RB_INITIALIZER(&head); 399.Ed 400.Pp 401The 402.Fn RB_INSERT 403macro inserts the new element 404.Fa elm 405into the tree. 406Upon success, 407.Va NULL 408is returned. 409If a matching element already exists in the tree, the insertion is 410aborted, and a pointer to the existing element is returned. 411.Pp 412The 413.Fn RB_REMOVE 414macro removes the element 415.Fa elm 416from the tree pointed by 417.Fa head . 418.Fn RB_REMOVE 419returns 420.Fa elm . 421.Pp 422The 423.Fn RB_FIND 424and 425.Fn RB_NFIND 426macros can be used to find a particular element in the tree. 427.Fn RB_FIND 428finds the node with the same key as 429.Fa elm . 430.Fn RB_NFIND 431finds the first node greater than or equal to the search key. 432.Bd -literal -offset indent 433struct TYPE find, *res; 434find.key = 30; 435res = RB_FIND(NAME, &head, &find); 436.Ed 437.Pp 438The 439.Fn RB_ROOT , 440.Fn RB_MIN , 441.Fn RB_MAX , 442.Fn RB_NEXT , 443and 444.Fn RB_PREV 445macros can be used to traverse the tree: 446.Bd -literal -offset indent 447for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np)) 448.Ed 449.Pp 450Or, for simplicity, one can use the 451.Fn RB_FOREACH 452or 453.Fn RB_FOREACH_REVERSE 454macros: 455.Bd -literal -offset indent 456RB_FOREACH(np, NAME, &head) 457.Ed 458.Pp 459The 460.Fn RB_EMPTY 461macro should be used to check whether a red-black tree is empty. 462.Sh EXAMPLES 463The following example demonstrates how to declare a red-black tree 464holding integers. 465Values are inserted into it and the contents of the tree are printed 466in order. 467Lastly, the internal structure of the tree is printed. 468.Bd -literal -offset 3n 469#include <sys/tree.h> 470#include <err.h> 471#include <stdio.h> 472#include <stdlib.h> 473 474struct node { 475 RB_ENTRY(node) entry; 476 int i; 477}; 478 479int 480intcmp(struct node *e1, struct node *e2) 481{ 482 return (e1->i < e2->i ? -1 : e1->i > e2->i); 483} 484 485RB_HEAD(inttree, node) head = RB_INITIALIZER(&head); 486RB_GENERATE(inttree, node, entry, intcmp) 487 488int testdata[] = { 489 20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18, 490 7, 11, 14 491}; 492 493void 494print_tree(struct node *n) 495{ 496 struct node *left, *right; 497 498 if (n == NULL) { 499 printf("nil"); 500 return; 501 } 502 left = RB_LEFT(n, entry); 503 right = RB_RIGHT(n, entry); 504 if (left == NULL && right == NULL) 505 printf("%d", n->i); 506 else { 507 printf("%d(", n->i); 508 print_tree(left); 509 printf(","); 510 print_tree(right); 511 printf(")"); 512 } 513} 514 515int 516main() 517{ 518 int i; 519 struct node *n; 520 521 for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) { 522 if ((n = malloc(sizeof(struct node))) == NULL) 523 err(1, NULL); 524 n->i = testdata[i]; 525 RB_INSERT(inttree, &head, n); 526 } 527 528 RB_FOREACH(n, inttree, &head) { 529 printf("%d\en", n->i); 530 } 531 print_tree(RB_ROOT(&head)); 532 printf("\en"); 533 return (0); 534} 535.Ed 536.Sh NOTES 537Trying to free a tree in the following way is a common error: 538.Bd -literal -offset indent 539SPLAY_FOREACH(var, NAME, &head) { 540 SPLAY_REMOVE(NAME, &head, var); 541 free(var); 542} 543free(head); 544.Ed 545.Pp 546Since 547.Va var 548is free'd, the 549.Fn FOREACH 550macro refers to a pointer that may have been reallocated already. 551Proper code needs a second variable. 552.Bd -literal -offset indent 553for (var = SPLAY_MIN(NAME, &head); var != NULL; var = nxt) { 554 nxt = SPLAY_NEXT(NAME, &head, var); 555 SPLAY_REMOVE(NAME, &head, var); 556 free(var); 557} 558.Ed 559.Sh AUTHORS 560The author of the tree macros is Niels Provos. 561