Module Name: src
Committed By: christos
Date: Fri Mar 29 21:16:31 UTC 2013
Modified Files:
src/share/man/man3: tree.3
Log Message:
sync with OpenBSD.
To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/share/man/man3/tree.3
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/share/man/man3/tree.3
diff -u src/share/man/man3/tree.3:1.8 src/share/man/man3/tree.3:1.9
--- src/share/man/man3/tree.3:1.8 Fri Mar 29 16:58:58 2013
+++ src/share/man/man3/tree.3 Fri Mar 29 17:16:31 2013
@@ -1,5 +1,5 @@
-.\" $NetBSD: tree.3,v 1.8 2013/03/29 20:58:58 pgoyette Exp $
-.\" $OpenBSD: tree.3,v 1.9 2003/05/20 09:13:38 jmc Exp $
+.\" $NetBSD: tree.3,v 1.9 2013/03/29 21:16:31 christos Exp $
+.\" $OpenBSD: tree.3,v 1.23 2011/07/09 08:43:01 jmc Exp $
.\"/*
.\" * Copyright 2002 Niels Provos <[email protected]>
.\" * All rights reserved.
@@ -12,11 +12,6 @@
.\" * 2. Redistributions in binary form must reproduce the above copyright
.\" * notice, this list of conditions and the following disclaimer in the
.\" * documentation and/or other materials provided with the distribution.
-.\" * 3. All advertising materials mentioning features or use of this software
-.\" * must display the following acknowledgement:
-.\" * This product includes software developed by Niels Provos.
-.\" * 4. The name of the author may not be used to endorse or promote products
-.\" * derived from this software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -29,7 +24,7 @@
.\" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" */
-.Dd May 5, 2010
+.Dd July 9 2011
.Dt TREE 3
.Os
.Sh NAME
@@ -51,20 +46,27 @@
.Nm SPLAY_INSERT ,
.Nm SPLAY_REMOVE ,
.Nm RB_PROTOTYPE ,
+.Nm RB_PROTOTYPE_STATIC ,
.Nm RB_GENERATE ,
+.Nm RB_GENERATE_STATIC ,
.Nm RB_ENTRY ,
.Nm RB_HEAD ,
.Nm RB_INITIALIZER ,
.Nm RB_ROOT ,
.Nm RB_EMPTY ,
.Nm RB_NEXT ,
+.Nm RB_PREV ,
.Nm RB_MIN ,
.Nm RB_MAX ,
.Nm RB_FIND ,
+.Nm RB_NFIND ,
.Nm RB_LEFT ,
.Nm RB_RIGHT ,
.Nm RB_PARENT ,
.Nm RB_FOREACH ,
+.Nm RB_FOREACH_SAFE ,
+.Nm RB_FOREACH_REVERSE ,
+.Nm RB_FOREACH_REVERSE_SAFE ,
.Nm RB_INIT ,
.Nm RB_INSERT ,
.Nm RB_REMOVE
@@ -78,7 +80,7 @@
.Ft "struct TYPE *"
.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head"
.Fn SPLAY_ROOT "SPLAY_HEAD *head"
-.Ft "bool"
+.Ft "int"
.Fn SPLAY_EMPTY "SPLAY_HEAD *head"
.Ft "struct TYPE *"
.Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
@@ -101,29 +103,38 @@
.Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
.Pp
.Fn RB_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP"
+.Fn RB_PROTOTYPE_STATIC "NAME" "TYPE" "FIELD" "CMP"
.Fn RB_GENERATE "NAME" "TYPE" "FIELD" "CMP"
+.Fn RB_GENERATE_STATIC "NAME" "TYPE" "FIELD" "CMP"
.Fn RB_ENTRY "TYPE"
.Fn RB_HEAD "HEADNAME" "TYPE"
.Fn RB_INITIALIZER "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_ROOT "RB_HEAD *head"
-.Ft "bool"
+.Ft "int"
.Fn RB_EMPTY "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
+.Fn RB_PREV "NAME" "RB_HEAD *head" "struct TYPE *elm"
+.Ft "struct TYPE *"
.Fn RB_MIN "NAME" "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_MAX "NAME" "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
+.Fn RB_NFIND "NAME" "RB_HEAD *head" "struct TYPE *elm"
+.Ft "struct TYPE *"
.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME"
.Ft "struct TYPE *"
.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME"
.Ft "struct TYPE *"
.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head"
+.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
+.Fn RB_FOREACH_REVERSE "VARNAME" "NAME" "RB_HEAD *head"
+.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
.Ft void
.Fn RB_INIT "RB_HEAD *head"
.Ft "struct TYPE *"
@@ -142,12 +153,12 @@ splay trees and red-black trees.
.Pp
In the macro definitions,
.Fa TYPE
-is the name tag of a user defined structure that must contain a field of type
-.Li SPLAY_ENTRY ,
+is the name tag of a user defined structure that must contain a field named
+.Fa FIELD ,
+of type
+.Li SPLAY_ENTRY
or
-.Li RB_ENTRY ,
-named
-.Fa ENTRYNAME .
+.Li RB_ENTRY .
The argument
.Fa HEADNAME
is the name tag of a user defined structure that must be declared
@@ -159,14 +170,16 @@ The argument
.Fa NAME
has to be a unique name prefix for every tree that is defined.
.Pp
-The function prototypes are declared with either
-.Li SPLAY_PROTOTYPE
+The function prototypes are declared with
+.Li SPLAY_PROTOTYPE ,
+.Li RB_PROTOTYPE ,
or
-.Li RB_PROTOTYPE .
-The function bodies are generated with either
-.Li SPLAY_GENERATE
+.Li RB_PROTOTYPE_STATIC .
+The function bodies are generated with
+.Li SPLAY_GENERATE ,
+.Li RB_GENERATE ,
or
-.Li RB_GENERATE .
+.Li RB_GENERATE_STATIC .
See the examples below for further explanation of how these macros are used.
.Sh SPLAY TREES
A splay tree is a self-organizing data structure.
@@ -228,7 +241,11 @@ macro, but should be used only once.
Finally,
the
.Fa CMP
+<<<<<<< tree.3
+argument is the name of a function used to compare trees' nodes
+=======
argument is the name of a function used to compare tree nodes
+>>>>>>> 1.8
with each other.
The function takes two arguments of type
.Fa "struct TYPE *" .
@@ -255,6 +272,11 @@ The
macro inserts the new element
.Fa elm
into the tree.
+Upon success,
+.Va NULL
+is returned.
+If a matching element already exists in the tree, the insertion is
+aborted, and a pointer to the existing element is returned.
.Pp
The
.Fn SPLAY_REMOVE
@@ -262,6 +284,11 @@ macro removes the element
.Fa elm
from the tree pointed by
.Fa head .
+Upon success, a pointer to the removed element is returned.
+.Va NULL
+is returned if
+.Fa elm
+is not present in the tree.
.Pp
The
.Fn SPLAY_FIND
@@ -269,7 +296,7 @@ macro can be used to find a particular e
.Bd -literal -offset indent
struct TYPE find, *res;
find.key = 30;
-res = SPLAY_FIND(NAME, head, \*[Am]find);
+res = SPLAY_FIND(NAME, \*[Am]head, \*[Am]find);
.Ed
.Pp
The
@@ -287,7 +314,7 @@ Or, for simplicity, one can use the
.Fn SPLAY_FOREACH
macro:
.Bd -literal -offset indent
-SPLAY_FOREACH(np, NAME, head)
+SPLAY_FOREACH(np, NAME, &head)
.Ed
.Pp
The
@@ -297,6 +324,7 @@ macro should be used to check whether a
A red-black tree is a binary search tree with the node color as an
extra attribute.
It fulfills a set of conditions:
+.Pp
.Bl -enum -compact -offset indent
.It
every search path from the root to a leaf consists of the same number of
@@ -333,7 +361,9 @@ macro declares a structure that allows e
In order to use the functions that manipulate the tree structure,
their prototypes need to be declared with the
.Fn RB_PROTOTYPE
-macro,
+or
+.Fn RB_PROTOTYPE_STATIC
+macros,
where
.Fa NAME
is a unique identifier for this particular tree.
@@ -348,15 +378,19 @@ argument is the name of the element defi
.Pp
The function bodies are generated with the
.Fn RB_GENERATE
-macro.
-It takes the same arguments as the
+or
+.Fn RB_GENERATE_STATIC
+macros.
+These macros take the same arguments as the
.Fn RB_PROTOTYPE
-macro, but should be used only once.
+and
+.Fn RB_PROTOTYPE_STATIC
+macros, but should be used only once.
.Pp
Finally,
the
.Fa CMP
-argument is the name of a function used to compare trees noded
+argument is the name of a function used to compare trees' nodes
with each other.
The function takes two arguments of type
.Fa "struct TYPE *" .
@@ -371,7 +405,7 @@ The
macro initializes the tree referenced by
.Fa head .
.Pp
-The redblack tree can also be initialized statically by using the
+The red-black tree can also be initialized statically by using the
.Fn RB_INITIALIZER
macro like this:
.Bd -literal -offset indent
@@ -383,6 +417,11 @@ The
macro inserts the new element
.Fa elm
into the tree.
+Upon success,
+.Va NULL
+is returned.
+If a matching element already exists in the tree, the insertion is
+aborted, and a pointer to the existing element is returned.
.Pp
The
.Fn RB_REMOVE
@@ -391,22 +430,34 @@ macro removes the element
from the tree pointed to by
.Fa head .
The element must be present in that tree.
+.Fn RB_REMOVE
+returns
+.Fa elm .
.Pp
The
.Fn RB_FIND
macro can be used to find a particular element in the tree.
+and
+.Fn RB_NFIND
+macros can be used to find a particular element in the tree.
+.Fn RB_FIND
+finds the node with the same key as
+.Fa elm .
+.Fn RB_NFIND
+finds the first node greater than or equal to the search key.
.Bd -literal -offset indent
struct TYPE find, *res;
find.key = 30;
-res = RB_FIND(NAME, head, \*[Am]find);
+res = RB_FIND(NAME, \*[Am]head, \*[Am]find);
.Ed
.Pp
The
.Fn RB_ROOT ,
.Fn RB_MIN ,
.Fn RB_MAX ,
+.Fn RB_NEXT,
and
-.Fn RB_NEXT
+.Fn RB_PREV
macros can be used to traverse the tree:
.Bd -literal -offset indent
for (np = RB_MIN(NAME, \*[Am]head); np != NULL; np = RB_NEXT(NAME, \*[Am]head, np))
@@ -414,14 +465,102 @@ for (np = RB_MIN(NAME, \*[Am]head); np !
.Pp
Or, for simplicity, one can use the
.Fn RB_FOREACH
-macro:
+or
+.Fn RB_FOREACH_REVERSE
+macros:
.Bd -literal -offset indent
-RB_FOREACH(np, NAME, head)
+RB_FOREACH(np, NAME, \*[Am]head)
.Ed
.Pp
+The macros
+.Fn RB_FOREACH_SAFE
+and
+.Fn RB_FOREACH_REVERSE_SAFE
+traverse the tree referenced by head
+in a forward or reverse direction respectively,
+assigning each element in turn to np.
+However, unlike their unsafe counterparts,
+they permit both the removal of np
+as well as freeing it from within the loop safely
+without interfering with the traversal.
+.Pp
The
.Fn RB_EMPTY
macro should be used to check whether a red-black tree is empty.
+.Sh EXAMPLES
+The following example demonstrates how to declare a red-black tree
+holding integers.
+Values are inserted into it and the contents of the tree are printed
+in order.
+Lastly, the internal structure of the tree is printed.
+.Bd -literal -offset 3n
+#include <sys/tree.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct node {
+ RB_ENTRY(node) entry;
+ int i;
+};
+
+int
+intcmp(struct node *e1, struct node *e2)
+{
+ return (e1->i < e2->i ? -1 : e1->i > e2->i);
+}
+
+RB_HEAD(inttree, node) head = RB_INITIALIZER(&head);
+RB_GENERATE(inttree, node, entry, intcmp)
+
+int testdata[] = {
+ 20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18,
+ 7, 11, 14
+};
+
+void
+print_tree(struct node *n)
+{
+ struct node *left, *right;
+
+ if (n == NULL) {
+ printf("nil");
+ return;
+ }
+ left = RB_LEFT(n, entry);
+ right = RB_RIGHT(n, entry);
+ if (left == NULL && right == NULL)
+ printf("%d", n->i);
+ else {
+ printf("%d(", n->i);
+ print_tree(left);
+ printf(",");
+ print_tree(right);
+ printf(")");
+ }
+}
+
+int
+main()
+{
+ int i;
+ struct node *n;
+
+ for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) {
+ if ((n = malloc(sizeof(struct node))) == NULL)
+ err(1, NULL);
+ n->i = testdata[i];
+ RB_INSERT(inttree, &head, n);
+ }
+
+ RB_FOREACH(n, inttree, &head) {
+ printf("%d\en", n->i);
+ }
+ print_tree(RB_ROOT(&head));
+ printf("\en");
+ return (0);
+}
+.Ed
.Sh NOTES
Some of these macros or functions perform no error checking,
and invalid usage leads to undefined behaviour.
@@ -431,8 +570,8 @@ that is not present in the tree is inval
.Pp
Trying to free a tree in the following way is a common error:
.Bd -literal -offset indent
-SPLAY_FOREACH(var, NAME, head) {
- SPLAY_REMOVE(NAME, head, var);
+SPLAY_FOREACH(var, NAME, &head) {
+ SPLAY_REMOVE(NAME, &head, var);
free(var);
}
free(head);
@@ -445,29 +584,29 @@ is free'd, the
macro refers to a pointer that may have been reallocated already.
Proper code needs a second variable.
.Bd -literal -offset indent
-for (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) {
- nxt = SPLAY_NEXT(NAME, head, var);
- SPLAY_REMOVE(NAME, head, var);
+for (var = SPLAY_MIN(NAME, &head); var != NULL; var = nxt) {
+ nxt = SPLAY_NEXT(NAME, &head, var);
+ SPLAY_REMOVE(NAME, &head, var);
free(var);
}
.Ed
-.Pp
-Both
-.Fn RB_INSERT
-and
-.Fn SPLAY_INSERT
-return
-.Dv NULL
-if the element was inserted in the tree successfully, otherwise they
-return a pointer to the element with the colliding key.
-.Pp
-Accordingly,
-.Fn RB_REMOVE
-and
-.Fn SPLAY_REMOVE
-return the pointer to the removed element, otherwise they return
-.Dv NULL
-to indicate an error.
+.\".Pp
+.\"Both
+.\".Fn RB_INSERT
+.\"and
+.\".Fn SPLAY_INSERT
+.\"return
+.\".Dv NULL
+.\"if the element was inserted in the tree successfully, otherwise they
+.\"return a pointer to the element with the colliding key.
+.\".Pp
+.\"Accordingly,
+.\".Fn RB_REMOVE
+.\"and
+.\".Fn SPLAY_REMOVE
+.\"return the pointer to the removed element, otherwise they return
+.\".Dv NULL
+.\"to indicate an error.
.Sh AUTHORS
The author of the tree macros is
.An Niels Provos .