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