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