1*72202f4aSwiz.\" $NetBSD: tree.3,v 1.14 2019/05/24 21:32:05 wiz Exp $ 218909555Schristos.\" $OpenBSD: tree.3,v 1.23 2011/07/09 08:43:01 jmc Exp $ 30a7c59f9Syamt.\"/* 40a7c59f9Syamt.\" * Copyright 2002 Niels Provos <provos@citi.umich.edu> 50a7c59f9Syamt.\" * All rights reserved. 60a7c59f9Syamt.\" * 70a7c59f9Syamt.\" * Redistribution and use in source and binary forms, with or without 80a7c59f9Syamt.\" * modification, are permitted provided that the following conditions 90a7c59f9Syamt.\" * are met: 100a7c59f9Syamt.\" * 1. Redistributions of source code must retain the above copyright 110a7c59f9Syamt.\" * notice, this list of conditions and the following disclaimer. 120a7c59f9Syamt.\" * 2. Redistributions in binary form must reproduce the above copyright 130a7c59f9Syamt.\" * notice, this list of conditions and the following disclaimer in the 140a7c59f9Syamt.\" * documentation and/or other materials provided with the distribution. 150a7c59f9Syamt.\" * 160a7c59f9Syamt.\" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 170a7c59f9Syamt.\" * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 180a7c59f9Syamt.\" * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 190a7c59f9Syamt.\" * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 200a7c59f9Syamt.\" * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 210a7c59f9Syamt.\" * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 220a7c59f9Syamt.\" * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 230a7c59f9Syamt.\" * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 240a7c59f9Syamt.\" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 250a7c59f9Syamt.\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 260a7c59f9Syamt.\" */ 27f66a7225Sryoon.Dd May 25, 2019 280a7c59f9Syamt.Dt TREE 3 290a7c59f9Syamt.Os 300a7c59f9Syamt.Sh NAME 310a7c59f9Syamt.Nm SPLAY_PROTOTYPE , 320a7c59f9Syamt.Nm SPLAY_GENERATE , 330a7c59f9Syamt.Nm SPLAY_ENTRY , 340a7c59f9Syamt.Nm SPLAY_HEAD , 350a7c59f9Syamt.Nm SPLAY_INITIALIZER , 360a7c59f9Syamt.Nm SPLAY_ROOT , 370a7c59f9Syamt.Nm SPLAY_EMPTY , 380a7c59f9Syamt.Nm SPLAY_NEXT , 390a7c59f9Syamt.Nm SPLAY_MIN , 400a7c59f9Syamt.Nm SPLAY_MAX , 410a7c59f9Syamt.Nm SPLAY_FIND , 420a7c59f9Syamt.Nm SPLAY_LEFT , 430a7c59f9Syamt.Nm SPLAY_RIGHT , 440a7c59f9Syamt.Nm SPLAY_FOREACH , 450a7c59f9Syamt.Nm SPLAY_INIT , 460a7c59f9Syamt.Nm SPLAY_INSERT , 470a7c59f9Syamt.Nm SPLAY_REMOVE , 480a7c59f9Syamt.Nm RB_PROTOTYPE , 4918909555Schristos.Nm RB_PROTOTYPE_STATIC , 500a7c59f9Syamt.Nm RB_GENERATE , 5118909555Schristos.Nm RB_GENERATE_STATIC , 520a7c59f9Syamt.Nm RB_ENTRY , 530a7c59f9Syamt.Nm RB_HEAD , 540a7c59f9Syamt.Nm RB_INITIALIZER , 550a7c59f9Syamt.Nm RB_ROOT , 560a7c59f9Syamt.Nm RB_EMPTY , 570a7c59f9Syamt.Nm RB_NEXT , 5818909555Schristos.Nm RB_PREV , 590a7c59f9Syamt.Nm RB_MIN , 600a7c59f9Syamt.Nm RB_MAX , 610a7c59f9Syamt.Nm RB_FIND , 6218909555Schristos.Nm RB_NFIND , 630a7c59f9Syamt.Nm RB_LEFT , 640a7c59f9Syamt.Nm RB_RIGHT , 650a7c59f9Syamt.Nm RB_PARENT , 660a7c59f9Syamt.Nm RB_FOREACH , 6718909555Schristos.Nm RB_FOREACH_SAFE , 6818909555Schristos.Nm RB_FOREACH_REVERSE , 6918909555Schristos.Nm RB_FOREACH_REVERSE_SAFE , 700a7c59f9Syamt.Nm RB_INIT , 710a7c59f9Syamt.Nm RB_INSERT , 720a7c59f9Syamt.Nm RB_REMOVE 73d3d460c5Swiz.Nd implementations of splay and red-black trees 740a7c59f9Syamt.Sh SYNOPSIS 75d3d460c5Swiz.In sys/tree.h 760a7c59f9Syamt.Fn SPLAY_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" 770a7c59f9Syamt.Fn SPLAY_GENERATE "NAME" "TYPE" "FIELD" "CMP" 780a7c59f9Syamt.Fn SPLAY_ENTRY "TYPE" 790a7c59f9Syamt.Fn SPLAY_HEAD "HEADNAME" "TYPE" 800a7c59f9Syamt.Ft "struct TYPE *" 810a7c59f9Syamt.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head" 820a7c59f9Syamt.Fn SPLAY_ROOT "SPLAY_HEAD *head" 8318909555Schristos.Ft "int" 840a7c59f9Syamt.Fn SPLAY_EMPTY "SPLAY_HEAD *head" 850a7c59f9Syamt.Ft "struct TYPE *" 860a7c59f9Syamt.Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 870a7c59f9Syamt.Ft "struct TYPE *" 880a7c59f9Syamt.Fn SPLAY_MIN "NAME" "SPLAY_HEAD *head" 890a7c59f9Syamt.Ft "struct TYPE *" 900a7c59f9Syamt.Fn SPLAY_MAX "NAME" "SPLAY_HEAD *head" 910a7c59f9Syamt.Ft "struct TYPE *" 920a7c59f9Syamt.Fn SPLAY_FIND "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 930a7c59f9Syamt.Ft "struct TYPE *" 940a7c59f9Syamt.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME" 950a7c59f9Syamt.Ft "struct TYPE *" 960a7c59f9Syamt.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" 970a7c59f9Syamt.Fn SPLAY_FOREACH "VARNAME" "NAME" "SPLAY_HEAD *head" 980a7c59f9Syamt.Ft void 990a7c59f9Syamt.Fn SPLAY_INIT "SPLAY_HEAD *head" 1000a7c59f9Syamt.Ft "struct TYPE *" 1010a7c59f9Syamt.Fn SPLAY_INSERT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 1020a7c59f9Syamt.Ft "struct TYPE *" 1030a7c59f9Syamt.Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" 1040a7c59f9Syamt.Pp 1050a7c59f9Syamt.Fn RB_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" 10618909555Schristos.Fn RB_PROTOTYPE_STATIC "NAME" "TYPE" "FIELD" "CMP" 1070a7c59f9Syamt.Fn RB_GENERATE "NAME" "TYPE" "FIELD" "CMP" 10818909555Schristos.Fn RB_GENERATE_STATIC "NAME" "TYPE" "FIELD" "CMP" 1090a7c59f9Syamt.Fn RB_ENTRY "TYPE" 1100a7c59f9Syamt.Fn RB_HEAD "HEADNAME" "TYPE" 1110a7c59f9Syamt.Fn RB_INITIALIZER "RB_HEAD *head" 1120a7c59f9Syamt.Ft "struct TYPE *" 1130a7c59f9Syamt.Fn RB_ROOT "RB_HEAD *head" 11418909555Schristos.Ft "int" 1150a7c59f9Syamt.Fn RB_EMPTY "RB_HEAD *head" 1160a7c59f9Syamt.Ft "struct TYPE *" 1170a7c59f9Syamt.Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm" 1180a7c59f9Syamt.Ft "struct TYPE *" 11918909555Schristos.Fn RB_PREV "NAME" "RB_HEAD *head" "struct TYPE *elm" 12018909555Schristos.Ft "struct TYPE *" 1210a7c59f9Syamt.Fn RB_MIN "NAME" "RB_HEAD *head" 1220a7c59f9Syamt.Ft "struct TYPE *" 1230a7c59f9Syamt.Fn RB_MAX "NAME" "RB_HEAD *head" 1240a7c59f9Syamt.Ft "struct TYPE *" 1250a7c59f9Syamt.Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm" 1260a7c59f9Syamt.Ft "struct TYPE *" 12718909555Schristos.Fn RB_NFIND "NAME" "RB_HEAD *head" "struct TYPE *elm" 12818909555Schristos.Ft "struct TYPE *" 1290a7c59f9Syamt.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" 1300a7c59f9Syamt.Ft "struct TYPE *" 1310a7c59f9Syamt.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" 1320a7c59f9Syamt.Ft "struct TYPE *" 1330a7c59f9Syamt.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" 1340a7c59f9Syamt.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head" 13518909555Schristos.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 13618909555Schristos.Fn RB_FOREACH_REVERSE "VARNAME" "NAME" "RB_HEAD *head" 13718909555Schristos.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 1380a7c59f9Syamt.Ft void 1390a7c59f9Syamt.Fn RB_INIT "RB_HEAD *head" 1400a7c59f9Syamt.Ft "struct TYPE *" 1410a7c59f9Syamt.Fn RB_INSERT "NAME" "RB_HEAD *head" "struct TYPE *elm" 1420a7c59f9Syamt.Ft "struct TYPE *" 1430a7c59f9Syamt.Fn RB_REMOVE "NAME" "RB_HEAD *head" "struct TYPE *elm" 1440a7c59f9Syamt.Sh DESCRIPTION 14509008336Sjruoho.Bf -symbolic 14609008336SjruohoThis is a legacy interface; for new code, 1478d682cb5Snjoly.Xr rbtree 3 14809008336Sjruohois preferred. 14909008336Sjruoho.Ef 15009008336Sjruoho.Pp 1510a7c59f9SyamtThese macros define data structures for different types of trees: 1520a7c59f9Syamtsplay trees and red-black trees. 1530a7c59f9Syamt.Pp 1540a7c59f9SyamtIn the macro definitions, 1550a7c59f9Syamt.Fa TYPE 15618909555Schristosis the name tag of a user defined structure that must contain a field named 15718909555Schristos.Fa FIELD , 15818909555Schristosof type 15918909555Schristos.Li SPLAY_ENTRY 1600a7c59f9Syamtor 16118909555Schristos.Li RB_ENTRY . 1620a7c59f9SyamtThe argument 1630a7c59f9Syamt.Fa HEADNAME 1640a7c59f9Syamtis the name tag of a user defined structure that must be declared 1650a7c59f9Syamtusing the macros 1660a7c59f9Syamt.Fn SPLAY_HEAD 1670a7c59f9Syamtor 1680a7c59f9Syamt.Fn RB_HEAD . 1690a7c59f9SyamtThe argument 1700a7c59f9Syamt.Fa NAME 1710a7c59f9Syamthas to be a unique name prefix for every tree that is defined. 1720a7c59f9Syamt.Pp 17318909555SchristosThe function prototypes are declared with 17418909555Schristos.Li SPLAY_PROTOTYPE , 17518909555Schristos.Li RB_PROTOTYPE , 1760a7c59f9Syamtor 17718909555Schristos.Li RB_PROTOTYPE_STATIC . 17818909555SchristosThe function bodies are generated with 17918909555Schristos.Li SPLAY_GENERATE , 18018909555Schristos.Li RB_GENERATE , 1810a7c59f9Syamtor 18218909555Schristos.Li RB_GENERATE_STATIC . 1830a7c59f9SyamtSee the examples below for further explanation of how these macros are used. 1840a7c59f9Syamt.Sh SPLAY TREES 1850a7c59f9SyamtA splay tree is a self-organizing data structure. 1860a7c59f9SyamtEvery operation on the tree causes a splay to happen. 1870a7c59f9SyamtThe splay moves the requested node to the root of the tree and partly 1880a7c59f9Syamtrebalances it. 1890a7c59f9Syamt.Pp 1900a7c59f9SyamtThis has the benefit that request locality causes faster lookups as 1910a7c59f9Syamtthe requested nodes move to the top of the tree. 1920a7c59f9SyamtOn the other hand, every lookup causes memory writes. 1930a7c59f9Syamt.Pp 1940a7c59f9SyamtThe Balance Theorem bounds the total access time for m operations 1950a7c59f9Syamtand n inserts on an initially empty tree as O((m + n)lg n). 1960a7c59f9SyamtThe amortized cost for a sequence of m accesses to a splay tree is O(lg n). 1970a7c59f9Syamt.Pp 1980a7c59f9SyamtA splay tree is headed by a structure defined by the 1990a7c59f9Syamt.Fn SPLAY_HEAD 2000a7c59f9Syamtmacro. 2010a7c59f9SyamtA 2020a7c59f9Syamt.Fa SPLAY_HEAD 2030a7c59f9Syamtstructure is declared as follows: 2040a7c59f9Syamt.Bd -literal -offset indent 2050a7c59f9SyamtSPLAY_HEAD(HEADNAME, TYPE) head; 2060a7c59f9Syamt.Ed 2070a7c59f9Syamt.Pp 2080a7c59f9Syamtwhere 2090a7c59f9Syamt.Fa HEADNAME 2100a7c59f9Syamtis the name of the structure to be defined, and struct 2110a7c59f9Syamt.Fa TYPE 2120a7c59f9Syamtis the type of the elements to be inserted into the tree. 2130a7c59f9Syamt.Pp 2140a7c59f9SyamtThe 2150a7c59f9Syamt.Fn SPLAY_ENTRY 2160a7c59f9Syamtmacro declares a structure that allows elements to be connected in the tree. 2170a7c59f9Syamt.Pp 2180a7c59f9SyamtIn order to use the functions that manipulate the tree structure, 2190a7c59f9Syamttheir prototypes need to be declared with the 2200a7c59f9Syamt.Fn SPLAY_PROTOTYPE 2210a7c59f9Syamtmacro, 2220a7c59f9Syamtwhere 2230a7c59f9Syamt.Fa NAME 2240a7c59f9Syamtis a unique identifier for this particular tree. 2250a7c59f9SyamtThe 2260a7c59f9Syamt.Fa TYPE 2270a7c59f9Syamtargument is the type of the structure that is being managed 2280a7c59f9Syamtby the tree. 2290a7c59f9SyamtThe 2300a7c59f9Syamt.Fa FIELD 2310a7c59f9Syamtargument is the name of the element defined by 2320a7c59f9Syamt.Fn SPLAY_ENTRY . 2330a7c59f9Syamt.Pp 2340a7c59f9SyamtThe function bodies are generated with the 2350a7c59f9Syamt.Fn SPLAY_GENERATE 2360a7c59f9Syamtmacro. 2370a7c59f9SyamtIt takes the same arguments as the 2380a7c59f9Syamt.Fn SPLAY_PROTOTYPE 2390a7c59f9Syamtmacro, but should be used only once. 2400a7c59f9Syamt.Pp 2410a7c59f9SyamtFinally, 2420a7c59f9Syamtthe 2430a7c59f9Syamt.Fa CMP 244027c677dSchristosargument is the name of a function used to compare tree nodes 2450a7c59f9Syamtwith each other. 2460a7c59f9SyamtThe function takes two arguments of type 2470a7c59f9Syamt.Fa "struct TYPE *" . 2480a7c59f9SyamtIf the first argument is smaller than the second, the function returns a 2490a7c59f9Syamtvalue smaller than zero. 2500a7c59f9SyamtIf they are equal, the function returns zero. 2510a7c59f9SyamtOtherwise, it should return a value greater than zero. 2520a7c59f9SyamtThe compare function defines the order of the tree elements. 2530a7c59f9Syamt.Pp 2540a7c59f9SyamtThe 2550a7c59f9Syamt.Fn SPLAY_INIT 2560a7c59f9Syamtmacro initializes the tree referenced by 2570a7c59f9Syamt.Fa head . 2580a7c59f9Syamt.Pp 2590a7c59f9SyamtThe splay tree can also be initialized statically by using the 2600a7c59f9Syamt.Fn SPLAY_INITIALIZER 2610a7c59f9Syamtmacro like this: 2620a7c59f9Syamt.Bd -literal -offset indent 26301869ca4SwizSPLAY_HEAD(HEADNAME, TYPE) head = SPLAY_INITIALIZER(&head); 2640a7c59f9Syamt.Ed 2650a7c59f9Syamt.Pp 2660a7c59f9SyamtThe 2670a7c59f9Syamt.Fn SPLAY_INSERT 2680a7c59f9Syamtmacro inserts the new element 2690a7c59f9Syamt.Fa elm 2700a7c59f9Syamtinto the tree. 27118909555SchristosUpon success, 2723f06676bSwiz.Dv NULL 27318909555Schristosis returned. 27418909555SchristosIf a matching element already exists in the tree, the insertion is 27518909555Schristosaborted, and a pointer to the existing element is returned. 2760a7c59f9Syamt.Pp 2770a7c59f9SyamtThe 2780a7c59f9Syamt.Fn SPLAY_REMOVE 2790a7c59f9Syamtmacro removes the element 2800a7c59f9Syamt.Fa elm 2810a7c59f9Syamtfrom the tree pointed by 2820a7c59f9Syamt.Fa head . 28318909555SchristosUpon success, a pointer to the removed element is returned. 2843f06676bSwiz.Dv NULL 28518909555Schristosis returned if 28618909555Schristos.Fa elm 28718909555Schristosis not present in the tree. 2880a7c59f9Syamt.Pp 2890a7c59f9SyamtThe 2900a7c59f9Syamt.Fn SPLAY_FIND 2910a7c59f9Syamtmacro can be used to find a particular element in the tree. 2920a7c59f9Syamt.Bd -literal -offset indent 2930a7c59f9Syamtstruct TYPE find, *res; 2940a7c59f9Syamtfind.key = 30; 29501869ca4Swizres = SPLAY_FIND(NAME, &head, &find); 2960a7c59f9Syamt.Ed 2970a7c59f9Syamt.Pp 2980a7c59f9SyamtThe 2990a7c59f9Syamt.Fn SPLAY_ROOT , 3000a7c59f9Syamt.Fn SPLAY_MIN , 3010a7c59f9Syamt.Fn SPLAY_MAX , 3020a7c59f9Syamtand 3030a7c59f9Syamt.Fn SPLAY_NEXT 3040a7c59f9Syamtmacros can be used to traverse the tree: 3050a7c59f9Syamt.Bd -literal -offset indent 30601869ca4Swizfor (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np)) 3070a7c59f9Syamt.Ed 3080a7c59f9Syamt.Pp 3090a7c59f9SyamtOr, for simplicity, one can use the 3100a7c59f9Syamt.Fn SPLAY_FOREACH 3110a7c59f9Syamtmacro: 3120a7c59f9Syamt.Bd -literal -offset indent 31318909555SchristosSPLAY_FOREACH(np, NAME, &head) 3140a7c59f9Syamt.Ed 3150a7c59f9Syamt.Pp 3160a7c59f9SyamtThe 3170a7c59f9Syamt.Fn SPLAY_EMPTY 3180a7c59f9Syamtmacro should be used to check whether a splay tree is empty. 3190a7c59f9Syamt.Sh RED-BLACK TREES 3200a7c59f9SyamtA red-black tree is a binary search tree with the node color as an 3210a7c59f9Syamtextra attribute. 3220a7c59f9SyamtIt fulfills a set of conditions: 32318909555Schristos.Pp 3240a7c59f9Syamt.Bl -enum -compact -offset indent 3250a7c59f9Syamt.It 3260a7c59f9Syamtevery search path from the root to a leaf consists of the same number of 3270a7c59f9Syamtblack nodes, 3280a7c59f9Syamt.It 3290a7c59f9Syamteach red node (except for the root) has a black parent, 3300a7c59f9Syamt.It 3310a7c59f9Syamteach leaf node is black. 3320a7c59f9Syamt.El 3330a7c59f9Syamt.Pp 3340a7c59f9SyamtEvery operation on a red-black tree is bounded as O(lg n). 3350a7c59f9SyamtThe maximum height of a red-black tree is 2lg (n+1). 3360a7c59f9Syamt.Pp 3370a7c59f9SyamtA red-black tree is headed by a structure defined by the 3380a7c59f9Syamt.Fn RB_HEAD 3390a7c59f9Syamtmacro. 3400a7c59f9SyamtA 3410a7c59f9Syamt.Fa RB_HEAD 3420a7c59f9Syamtstructure is declared as follows: 3430a7c59f9Syamt.Bd -literal -offset indent 3440a7c59f9SyamtRB_HEAD(HEADNAME, TYPE) head; 3450a7c59f9Syamt.Ed 3460a7c59f9Syamt.Pp 3470a7c59f9Syamtwhere 3480a7c59f9Syamt.Fa HEADNAME 3490a7c59f9Syamtis the name of the structure to be defined, and struct 3500a7c59f9Syamt.Fa TYPE 3510a7c59f9Syamtis the type of the elements to be inserted into the tree. 3520a7c59f9Syamt.Pp 3530a7c59f9SyamtThe 3540a7c59f9Syamt.Fn RB_ENTRY 3550a7c59f9Syamtmacro declares a structure that allows elements to be connected in the tree. 3560a7c59f9Syamt.Pp 3570a7c59f9SyamtIn order to use the functions that manipulate the tree structure, 3580a7c59f9Syamttheir prototypes need to be declared with the 3590a7c59f9Syamt.Fn RB_PROTOTYPE 36018909555Schristosor 36118909555Schristos.Fn RB_PROTOTYPE_STATIC 36218909555Schristosmacros, 3630a7c59f9Syamtwhere 3640a7c59f9Syamt.Fa NAME 3650a7c59f9Syamtis a unique identifier for this particular tree. 3660a7c59f9SyamtThe 3670a7c59f9Syamt.Fa TYPE 3680a7c59f9Syamtargument is the type of the structure that is being managed 3690a7c59f9Syamtby the tree. 3700a7c59f9SyamtThe 3710a7c59f9Syamt.Fa FIELD 3720a7c59f9Syamtargument is the name of the element defined by 3730a7c59f9Syamt.Fn RB_ENTRY . 3740a7c59f9Syamt.Pp 3750a7c59f9SyamtThe function bodies are generated with the 3760a7c59f9Syamt.Fn RB_GENERATE 37718909555Schristosor 37818909555Schristos.Fn RB_GENERATE_STATIC 37918909555Schristosmacros. 38018909555SchristosThese macros take the same arguments as the 3810a7c59f9Syamt.Fn RB_PROTOTYPE 38218909555Schristosand 38318909555Schristos.Fn RB_PROTOTYPE_STATIC 38418909555Schristosmacros, but should be used only once. 3850a7c59f9Syamt.Pp 3860a7c59f9SyamtFinally, 3870a7c59f9Syamtthe 3880a7c59f9Syamt.Fa CMP 38918909555Schristosargument is the name of a function used to compare trees' nodes 3900a7c59f9Syamtwith each other. 3910a7c59f9SyamtThe function takes two arguments of type 3920a7c59f9Syamt.Fa "struct TYPE *" . 3930a7c59f9SyamtIf the first argument is smaller than the second, the function returns a 3940a7c59f9Syamtvalue smaller than zero. 3950a7c59f9SyamtIf they are equal, the function returns zero. 3960a7c59f9SyamtOtherwise, it should return a value greater than zero. 3970a7c59f9SyamtThe compare function defines the order of the tree elements. 3980a7c59f9Syamt.Pp 3990a7c59f9SyamtThe 4000a7c59f9Syamt.Fn RB_INIT 4010a7c59f9Syamtmacro initializes the tree referenced by 4020a7c59f9Syamt.Fa head . 4030a7c59f9Syamt.Pp 40418909555SchristosThe red-black tree can also be initialized statically by using the 4050a7c59f9Syamt.Fn RB_INITIALIZER 4060a7c59f9Syamtmacro like this: 4070a7c59f9Syamt.Bd -literal -offset indent 40801869ca4SwizRB_HEAD(HEADNAME, TYPE) head = RB_INITIALIZER(&head); 4090a7c59f9Syamt.Ed 4100a7c59f9Syamt.Pp 4110a7c59f9SyamtThe 4120a7c59f9Syamt.Fn RB_INSERT 4130a7c59f9Syamtmacro inserts the new element 4140a7c59f9Syamt.Fa elm 4150a7c59f9Syamtinto the tree. 41618909555SchristosUpon success, 4173f06676bSwiz.Dv NULL 41818909555Schristosis returned. 41918909555SchristosIf a matching element already exists in the tree, the insertion is 42018909555Schristosaborted, and a pointer to the existing element is returned. 4210a7c59f9Syamt.Pp 4220a7c59f9SyamtThe 4230a7c59f9Syamt.Fn RB_REMOVE 4240a7c59f9Syamtmacro removes the element 4250a7c59f9Syamt.Fa elm 426235284ebSdhollandfrom the tree pointed to by 4270a7c59f9Syamt.Fa head . 428235284ebSdhollandThe element must be present in that tree. 42918909555Schristos.Fn RB_REMOVE 43018909555Schristosreturns 43118909555Schristos.Fa elm . 4320a7c59f9Syamt.Pp 4330a7c59f9SyamtThe 4340a7c59f9Syamt.Fn RB_FIND 4350a7c59f9Syamtmacro can be used to find a particular element in the tree. 43618909555Schristosand 43718909555Schristos.Fn RB_NFIND 43818909555Schristosmacros can be used to find a particular element in the tree. 43918909555Schristos.Fn RB_FIND 44018909555Schristosfinds the node with the same key as 44118909555Schristos.Fa elm . 44218909555Schristos.Fn RB_NFIND 44318909555Schristosfinds the first node greater than or equal to the search key. 4440a7c59f9Syamt.Bd -literal -offset indent 4450a7c59f9Syamtstruct TYPE find, *res; 4460a7c59f9Syamtfind.key = 30; 44701869ca4Swizres = RB_FIND(NAME, &head, &find); 4480a7c59f9Syamt.Ed 4490a7c59f9Syamt.Pp 4500a7c59f9SyamtThe 4510a7c59f9Syamt.Fn RB_ROOT , 4520a7c59f9Syamt.Fn RB_MIN , 4530a7c59f9Syamt.Fn RB_MAX , 45418909555Schristos.Fn RB_NEXT , 4550a7c59f9Syamtand 45618909555Schristos.Fn RB_PREV 4570a7c59f9Syamtmacros can be used to traverse the tree: 4580a7c59f9Syamt.Bd -literal -offset indent 45901869ca4Swizfor (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np)) 4600a7c59f9Syamt.Ed 4610a7c59f9Syamt.Pp 4620a7c59f9SyamtOr, for simplicity, one can use the 4630a7c59f9Syamt.Fn RB_FOREACH 46418909555Schristosor 46518909555Schristos.Fn RB_FOREACH_REVERSE 46618909555Schristosmacros: 4670a7c59f9Syamt.Bd -literal -offset indent 46801869ca4SwizRB_FOREACH(np, NAME, &head) 4690a7c59f9Syamt.Ed 4700a7c59f9Syamt.Pp 47118909555SchristosThe macros 47218909555Schristos.Fn RB_FOREACH_SAFE 47318909555Schristosand 47418909555Schristos.Fn RB_FOREACH_REVERSE_SAFE 47518909555Schristostraverse the tree referenced by head 47618909555Schristosin a forward or reverse direction respectively, 47718909555Schristosassigning each element in turn to np. 47818909555SchristosHowever, unlike their unsafe counterparts, 47918909555Schristosthey permit both the removal of np 48018909555Schristosas well as freeing it from within the loop safely 48118909555Schristoswithout interfering with the traversal. 48218909555Schristos.Pp 4830a7c59f9SyamtThe 4840a7c59f9Syamt.Fn RB_EMPTY 4850ee5148aSpookamacro should be used to check whether a red-black tree is empty. 48618909555Schristos.Sh EXAMPLES 48718909555SchristosThe following example demonstrates how to declare a red-black tree 48818909555Schristosholding integers. 48918909555SchristosValues are inserted into it and the contents of the tree are printed 49018909555Schristosin order. 49118909555SchristosLastly, the internal structure of the tree is printed. 49218909555Schristos.Bd -literal -offset 3n 49318909555Schristos#include <sys/tree.h> 49418909555Schristos#include <err.h> 49518909555Schristos#include <stdio.h> 49618909555Schristos#include <stdlib.h> 49718909555Schristos 49818909555Schristosstruct node { 49918909555Schristos RB_ENTRY(node) entry; 50018909555Schristos int i; 50118909555Schristos}; 50218909555Schristos 50318909555Schristosint 50418909555Schristosintcmp(struct node *e1, struct node *e2) 50518909555Schristos{ 50618909555Schristos return (e1->i < e2->i ? -1 : e1->i > e2->i); 50718909555Schristos} 50818909555Schristos 50918909555SchristosRB_HEAD(inttree, node) head = RB_INITIALIZER(&head); 51018909555SchristosRB_GENERATE(inttree, node, entry, intcmp) 51118909555Schristos 51218909555Schristosint testdata[] = { 51318909555Schristos 20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18, 51418909555Schristos 7, 11, 14 51518909555Schristos}; 51618909555Schristos 51718909555Schristosvoid 51818909555Schristosprint_tree(struct node *n) 51918909555Schristos{ 52018909555Schristos struct node *left, *right; 52118909555Schristos 52218909555Schristos if (n == NULL) { 52318909555Schristos printf("nil"); 52418909555Schristos return; 52518909555Schristos } 52618909555Schristos left = RB_LEFT(n, entry); 52718909555Schristos right = RB_RIGHT(n, entry); 52818909555Schristos if (left == NULL && right == NULL) 52918909555Schristos printf("%d", n->i); 53018909555Schristos else { 53118909555Schristos printf("%d(", n->i); 53218909555Schristos print_tree(left); 53318909555Schristos printf(","); 53418909555Schristos print_tree(right); 53518909555Schristos printf(")"); 53618909555Schristos } 53718909555Schristos} 53818909555Schristos 53918909555Schristosint 54018909555Schristosmain() 54118909555Schristos{ 54218909555Schristos int i; 54318909555Schristos struct node *n; 54418909555Schristos 54518909555Schristos for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) { 54618909555Schristos if ((n = malloc(sizeof(struct node))) == NULL) 54718909555Schristos err(1, NULL); 54818909555Schristos n->i = testdata[i]; 54918909555Schristos RB_INSERT(inttree, &head, n); 55018909555Schristos } 55118909555Schristos 55218909555Schristos RB_FOREACH(n, inttree, &head) { 55318909555Schristos printf("%d\en", n->i); 55418909555Schristos } 55518909555Schristos print_tree(RB_ROOT(&head)); 55618909555Schristos printf("\en"); 55718909555Schristos return (0); 55818909555Schristos} 55918909555Schristos.Ed 5600a7c59f9Syamt.Sh NOTES 5613fa869bcSapbSome of these macros or functions perform no error checking, 5623fa869bcSapband invalid usage leads to undefined behaviour. 5633fa869bcSapbIn the case of macros or functions that expect their arguments 5643fa869bcSapbto be elements that are present in the tree, passing an element 5653fa869bcSapbthat is not present in the tree is invalid. 5663fa869bcSapb.Pp 5670a7c59f9SyamtTrying to free a tree in the following way is a common error: 5680a7c59f9Syamt.Bd -literal -offset indent 56918909555SchristosSPLAY_FOREACH(var, NAME, &head) { 57018909555Schristos SPLAY_REMOVE(NAME, &head, var); 5710a7c59f9Syamt free(var); 5720a7c59f9Syamt} 5730a7c59f9Syamtfree(head); 5740a7c59f9Syamt.Ed 5750a7c59f9Syamt.Pp 5760a7c59f9SyamtSince 5770a7c59f9Syamt.Va var 5780a7c59f9Syamtis free'd, the 5790a7c59f9Syamt.Fn FOREACH 5800a7c59f9Syamtmacro refers to a pointer that may have been reallocated already. 5810a7c59f9SyamtProper code needs a second variable. 5820a7c59f9Syamt.Bd -literal -offset indent 58318909555Schristosfor (var = SPLAY_MIN(NAME, &head); var != NULL; var = nxt) { 58418909555Schristos nxt = SPLAY_NEXT(NAME, &head, var); 58518909555Schristos SPLAY_REMOVE(NAME, &head, var); 5860a7c59f9Syamt free(var); 5870a7c59f9Syamt} 5880a7c59f9Syamt.Ed 58918909555Schristos.\".Pp 59018909555Schristos.\"Both 59118909555Schristos.\".Fn RB_INSERT 59218909555Schristos.\"and 59318909555Schristos.\".Fn SPLAY_INSERT 59418909555Schristos.\"return 59518909555Schristos.\".Dv NULL 59618909555Schristos.\"if the element was inserted in the tree successfully, otherwise they 59718909555Schristos.\"return a pointer to the element with the colliding key. 59818909555Schristos.\".Pp 59918909555Schristos.\"Accordingly, 60018909555Schristos.\".Fn RB_REMOVE 60118909555Schristos.\"and 60218909555Schristos.\".Fn SPLAY_REMOVE 60318909555Schristos.\"return the pointer to the removed element, otherwise they return 60418909555Schristos.\".Dv NULL 60518909555Schristos.\"to indicate an error. 606f66a7225Sryoon.Sh SEE ALSO 607f66a7225Sryoon.Xr rbtree 3 6080a7c59f9Syamt.Sh AUTHORS 609d3d460c5SwizThe author of the tree macros is 610d3d460c5Swiz.An Niels Provos . 611