Add the RB_NFIND() macro, which is useful for red-black tree searches

for which there may not be an exact match.

Reviewed by:	glebius, julian
Approved by:	markm (mentor)
This commit is contained in:
Jason Evans 2006-01-11 15:48:36 +00:00
parent 3b33fbe7d4
commit 06115e083a
3 changed files with 38 additions and 1 deletions

View File

@ -108,6 +108,7 @@ MLINKS+= timeradd.3 timerclear.3 \
MLINKS+= tree.3 RB_EMPTY.3 \
tree.3 RB_ENTRY.3 \
tree.3 RB_FIND.3 \
tree.3 RB_NFIND.3 \
tree.3 RB_FOREACH.3 \
tree.3 RB_GENERATE.3 \
tree.3 RB_HEAD.3 \

View File

@ -62,6 +62,7 @@
.Nm RB_MIN ,
.Nm RB_MAX ,
.Nm RB_FIND ,
.Nm RB_NFIND ,
.Nm RB_LEFT ,
.Nm RB_RIGHT ,
.Nm RB_PARENT ,
@ -118,6 +119,8 @@
.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"
@ -405,7 +408,9 @@ from the tree pointed by
.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.
.Bd -literal -offset indent
struct TYPE find, *res;
find.key = 30;

View File

@ -382,6 +382,7 @@ void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
struct type *name##_RB_REMOVE(struct name *, struct type *); \
struct type *name##_RB_INSERT(struct name *, struct type *); \
struct type *name##_RB_FIND(struct name *, struct type *); \
struct type *name##_RB_NFIND(struct name *, struct type *); \
struct type *name##_RB_NEXT(struct type *); \
struct type *name##_RB_MINMAX(struct name *, int); \
\
@ -628,6 +629,35 @@ name##_RB_FIND(struct name *head, struct type *elm) \
return (NULL); \
} \
\
/* Finds the first node greater than or equal to the search key */ \
struct type * \
name##_RB_NFIND(struct name *head, struct type *elm) \
{ \
struct type *ret = RB_ROOT(head); \
struct type *tmp; \
int comp; \
while (ret && (comp = cmp(elm, ret)) != 0) { \
if (comp < 0) { \
if ((tmp = RB_LEFT(ret, field)) == NULL) \
break; \
ret = tmp; \
} else { \
if ((tmp = RB_RIGHT(ret, field)) == NULL) { \
tmp = ret; \
ret = RB_PARENT(ret, field); \
while (ret && tmp == RB_RIGHT(ret, \
field)) { \
tmp = ret; \
ret = RB_PARENT(ret, field); \
} \
break; \
} \
ret = tmp; \
} \
} \
return (ret); \
} \
\
/* ARGSUSED */ \
struct type * \
name##_RB_NEXT(struct type *elm) \
@ -671,6 +701,7 @@ name##_RB_MINMAX(struct name *head, int val) \
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)