xref: /netbsd-src/share/man/man3/tree.3 (revision 72202f4a79609c703ef7fb0f42f7a1301c8aa99e)
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