blob: 8f09a7894ef7ec20babbada12e27d6b92049411a [file] [log] [blame]
.\" Copyright 2000 by Damian Ivereigh <damian@cisco.com>
.\"
.\" Permission is granted to make and distribute verbatim copies of this
.\" manual provided the copyright notice and this permission notice are
.\" preserved on all copies.
.\"
.\" Permission is granted to copy and distribute modified versions of this
.\" manual under the conditions for verbatim copying, provided that the
.\" entire resulting derived work is distributed under the terms of a
.\" permission notice identical to this one.
.\"
.\" Since the Linux kernel and libraries are constantly changing, this
.\" manual page may be incorrect or out-of-date. The author(s) assume no
.\" responsibility for errors or omissions, or for damages resulting from
.\" the use of the information contained herein. The author(s) may not
.\" have taken the same level of care in the production of this manual,
.\" which is licensed free of charge, as they might when working
.\" professionally.
.\"
.\" Formatted or processed versions of this manual, if unaccompanied by
.\" the source, must acknowledge the copyright and authors of this work.
.\"
.TH RBINIT 3 "May 23, 2000" "GNU" "Linux Programmer's Manual"
.SH NAME
rbinit, rbdestroy, rbsearch, rbfind, rbdelete, rbwalk \- manage a red-black binary tree
.SH SYNOPSIS
.nf
.B #include <redblack.h>
.sp
.BI "struct rbtree *rbinit ("
.BI " int (*" cmp ")(const void *" p1 ", const void *" p2 ", "
.BI " const void *" config "), "
.BI " const void *" config ");"
.sp
.BI "void rbdestroy (struct rbtree *" rb ");"
.sp
.BI "const void *rbsearch (const void *" key ", struct rbtree *" rb ");"
.sp
.BI "const void *rbfind (const void *" key ", struct rbtree *" rb ");"
.sp
.BI "const void *rblookup (int" mode ", const void *" key ", "
.BI " struct rbtree *" rb ");"
.sp
.BI "const void *rbdelete (const void *" key ", struct rbtree *" rb ");"
.sp
.BI "void rbwalk (const struct rbtree *" rb ", "
.BI " void (*" action ")(const void *" nodep ", "
.BI " const VISIT " which ", "
.BI " const int " depth ", void *" arg "), "
.BI " void *" arg ");"
.sp
.BI "const void *rbmin (struct rbtree *" rb ");"
.sp
.BI "const void *rbmax (struct rbtree *" rb ");"
.RE
.fi
.SH DESCRIPTION
\fBrbinit\fP, \fBrbdestroy\fP, \fBrbsearch\fP, \fBrbfind\fP,
\fBrblookup\fP, \fBrbdelete\fP and \fBrbwalk\fP manage a redblack balanced
binary tree. They are generalized from "Introduction to Algorithms"
by Cormen, Leiserson & Rivest. The last field in each node of the tree
is a pointer to the corresponding data item. (The calling program must
store the actual data.) \fIcmp\fP points to a comparison routine, which
takes pointers to three items. The first two are pointers to the data to
be compared. The last is some static configuration data which is passed
to the comparison routine each time. It should return an integer which
is negative, zero, or positive, depending on whether the first item is
less than, equal to, or greater than the second.
.PP
\fBrbinit\fP initialises the tree, stores a pointer to the comparison
routine and any config data, which may be NULL if not required. A
pointer to type struct rbtree is returned and is used in subsequent
calls into the redblack library.
.PP
A typical compare routine would be defined thus:
.sp
.nf
.BI "int " cmp "(const void *" p1 ", const void *" p2 ", "
.BI " const void *" config ");"
.fi
.sp
The arguments \fBp1\fP and \fBp2\fP are the pointers to the data to be
compared. \fBconfig\fP is used to alter the behaviour of the compare
routine in a fixed way. For example using the same compare routine
with multiple trees - with this compare routine behaving differently
for each tree. The \fBconfig\fP argument is just passed straight through
to the compare routine and if not used may be set to \fBNULL\fP.
\fBN.B.\fP It is very important that the compare routine
be deterministic and stateless, i.e. always return the same result for
the same given data.
.PP
\fBrbdestroy\fP destroys any tree allocated by \fBrbinit\fP and will
free up any allocated nodes. N.B. The users data is not freed, since it
is the users responsibility to store (and free) this data.
.PP
\fBrbsearch\fP searches the tree for an item. \fIkey\fP points to the
item to be searched for. \fIrb\fP points to the structure returned
by \fBrbinit\fP. If the item is found in the tree, then \fBrbsearch\fP
returns a pointer to it. If it is not found, then \fBrbsearch\fP adds
it, and returns a pointer to the newly added item.
.PP
\fBrbfind\fP is like \fBrbsearch\fP, except that if the item is not
found, then \fBrbfind\fP returns \fBNULL\fP.
.PP
\fBrbdelete\fP deletes an item from the tree. Its arguments are the
same as for \fBrbsearch\fP.
.PP
\fBrblookup\fP allows the traversing of the tree. Which key is returned
is determined by \fImode\fP. If requested key cannot be found then
\fBrblookup\fP returns \fBNULL\fP. \fImode\fP can be any one of the following:
.TP
.B RB_LUEQUAL
Returns node exactly matching the key. This is equivalent to \fBrbfind\fP
.TP
.B RB_LUGTEQ
Returns the node exactly matching the specified key, if this is not found
then the next node that is greater than the specified key is returned.
.TP
.B RB_LULTEQ
Returns the node exactly matching the specified key, if this is not found
then the next node that is less than the specified key is returned.
.TP
.B RB_LUGREAT
Returns the node that is just greater than the specified key - not equal to.
This mode is similar to \fBRB_LUNEXT\fP except that the specified key need
not exist in the tree.
.TP
.B RB_LULESS
Returns the node that is just less than the specified key - not equal to.
This mode is similar to \fBRB_LUPREV\fP except that the specified key need
not exist in the tree.
.TP
.B RB_LUNEXT
Looks for the key specified, if not found returns NULL. If the node is found
returns the next node that is greater than the one found (or NULL if there
is no next node). This is used to step through the tree in order.
.TP
.B RB_LUPREV
Looks for the key specified, if not found returns NULL. If the node is found
returns the previous node that is less than the one found (or NULL if there
is no previous node). This is used to step through the tree in reverse order.
.TP
.B RB_LUFIRST
Returns the first node in the tree (i.e. the one with the lowest key). The
argument \fIkey\fP is ignored.
.TP
.B RB_LULAST
Returns the last node in the tree (i.e. the one with the largest key). The
argument \fIkey\fP is ignored.
.PP
\fBrbwalk\fP performs depth-first, left-to-right traversal of a binary
tree. \fIroot\fP points to the starting node for the traversal. If
that node is not the root, then only part of the tree will be visited.
\fBrbwalk\fP calls the user function \fIaction\fP each time a node is
visited (that is, three times for an internal node, and once for a
leaf). \fIaction\fP, in turn, takes three arguments. The first is a
pointer to the node being visited. The second is an integer which
takes on the values \fBpreorder\fP, \fBpostorder\fP, and
\fBendorder\fP depending on whether this is the first, second, or
third visit to the internal node, or \fBleaf\fP if it is the single
visit to a leaf node. (These symbols are defined in
\fI<search.h>\fP which is automatically included with \fI<redblack.h>\fP.)
The third argument is the depth of the node, with
zero being the root.
.PP
\fBrbmin\fP is a macro which delivers the minimum (first) node in the tree.
.PP
\fBrbmax\fP is a macro which delivers the maximum (last) node in the tree.
.PP
.SH "READING BACK THE DATA"
There are essentially three different ways that the data can be read out of
the tree. Each with different optimisations.
.PP
\fBrblookup\fP is designed for ad-hoc moving around the tree (forward,
backwards and jumping to new places). However this is not so good when
wanting to read all the data out in sequence using RB_LUFIRST & RB_LUNEXT,
since the key needs to be re-found each time, which can be particularly
problematic if that key has been deleted! (see example1.c)
.PP
\fBrbwalk\fP actually walks the tree from beginning to end, calling a
callback-function at every stage that it deals with a node. This is also
useful if you want to work within the tree as you walk (e.g. deleting as you
go). It is also fairly compatible with \fBtwalk(3)\fP. However it requires
the use of a callback function which can be difficult to use if this needs
to change the state of the routine calling \fBrbwalk\fP (you have to use
global variables). (see example2.c)
.PP
\fBrbopenlist\fP, \fBrbreadlist\fP and \fBrbcloselist\fP (described in a
seperate man page) work best for reading the entire tree in order, each
call to \fBreadlist\fP delivering another node. (see example3.c)
.PP
.SH "RETURN VALUE"
\fBrbinit\fP returns a pointer to the new tree, \fBNULL\fP if there
was insufficient memory to allocate the structure.
\fBrbdestroy\fP has no return value.
\fBrbwalk\fP has no return value.
\fBrbsearch\fP returns a pointer to a matching item in the tree, or to
the newly added item, or \fBNULL\fP if there was insufficient memory
to add the item. \fBrbfind\fP returns a pointer to the item, or
\fBNULL\fP if no match is found. If there
are multiple elements that match the key, the element returned is
unspecified.
.PP
\fBtdelete\fP returns a pointer to the data for the item deleted, or
\fBNULL\fP if the item was not found.
.PP
\fBrbsearch\fP, \fBrbfind\fP, and \fBrbdelete\fP also
return \fBNULL\fP if \fIrb\fP was \fBNULL\fP on entry.
.SH WARNINGS
\fBrbdelete\fP frees the memory required for the node in the tree.
The user is responsible for freeing the memory for the corresponding
data.
.SH EXAMPLE
The following program inserts twelve random numbers into a binary
tree, then prints the numbers in order.
.sp
.nf
#include <redblack.h>
#include <stdlib.h>
#include <stdio.h>
void *xmalloc(unsigned n)
{
void *p;
p = malloc(n);
if(p) return p;
fprintf(stderr, "insufficient memory\\n");
exit(1);
}
int compare(const void *pa, const void *pb, const void *config)
{
if(*(int *)pa < *(int *)pb) return -1;
if(*(int *)pa > *(int *)pb) return 1;
return 0;
}
int main()
{
int i, *ptr;
void *val;
struct rbtree *rb;
srand(getpid());
if ((rb=rbinit(compare, NULL))==NULL)
{
fprintf(stderr, "insufficient memory\\n");
exit(1);
}
for (i = 0; i < 12; i++)
{
ptr = (int *)xmalloc(sizeof(int));
*ptr = rand()&0xff;
val = rbsearch((void *)ptr, rb);
if(val == NULL) exit(1);
}
for(val=rblookup(RB_LUFIRST, NULL, rb);
val!=NULL;
val=rblookup(RB_LUNEXT, val, rb))
{
printf("%6d\\n", *(int *)val);
}
rbdestroy(rb);
return 0;
}
.fi
.SH "CONFORMING TO"
SVID
.SH "SEE ALSO"
.BR rbopenlist (3),
.BR rbgen (1),
.BR tsearch (3).