1 /* $NetBSD: tsearch.c,v 1.1.1.2 2014/04/24 12:45:52 pettai Exp $ */
4 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
5 * the AT&T man page says.
7 * The node_t structure is for internal use only, lint doesn't grok it.
9 * Written by reading the System V Interface Definition, not the code.
11 * Totally public domain.
13 * NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp
14 * NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp
15 * NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp
16 * NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp
20 #include <krb5/roken.h>
26 struct node
*llink
, *rlink
;
30 #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
34 * find or insert datum into search tree
37 * vkey: key to be located
38 * vrootp: address of tree root
41 ROKEN_LIB_FUNCTION
void *
42 rk_tsearch(const void *vkey
, void **vrootp
,
43 int (*compar
)(const void *, const void *))
46 node_t
**rootp
= (node_t
**)vrootp
;
51 while (*rootp
!= NULL
) { /* Knuth's T1: */
54 if ((r
= (*compar
)(vkey
, (*rootp
)->key
)) == 0) /* T2: */
55 return *rootp
; /* we found it! */
58 &(*rootp
)->llink
: /* T3: follow left branch */
59 &(*rootp
)->rlink
; /* T4: follow right branch */
62 q
= malloc(sizeof(node_t
)); /* T5: key not found */
63 if (q
!= 0) { /* make new node */
64 *rootp
= q
; /* link new node to old */
65 /* LINTED const castaway ok */
66 q
->key
= __DECONST(void *, vkey
); /* initialize new node */
67 q
->llink
= q
->rlink
= NULL
;
73 * Walk the nodes of a tree
76 * root: Root of the tree to be walked
79 trecurse(const node_t
*root
, void (*action
)(const void *, VISIT
, int),
83 if (root
->llink
== NULL
&& root
->rlink
== NULL
)
84 (*action
)(root
, leaf
, level
);
86 (*action
)(root
, preorder
, level
);
87 if (root
->llink
!= NULL
)
88 trecurse(root
->llink
, action
, level
+ 1);
89 (*action
)(root
, postorder
, level
);
90 if (root
->rlink
!= NULL
)
91 trecurse(root
->rlink
, action
, level
+ 1);
92 (*action
)(root
, endorder
, level
);
97 * Walk the nodes of a tree
100 * vroot: Root of the tree to be walked
102 ROKEN_LIB_FUNCTION
void
103 rk_twalk(const void *vroot
,
104 void (*action
)(const void *, VISIT
, int))
106 if (vroot
!= NULL
&& action
!= NULL
)
107 trecurse(vroot
, action
, 0);
111 * delete node with given key
113 * vkey: key to be deleted
114 * vrootp: address of the root of the tree
115 * compar: function to carry out node comparisons
117 ROKEN_LIB_FUNCTION
void *
118 rk_tdelete(const void * vkey
, void ** vrootp
,
119 int (*compar
)(const void *, const void *))
121 node_t
**rootp
= (node_t
**)vrootp
;
125 if (rootp
== NULL
|| (p
= *rootp
) == NULL
)
128 while ((cmp
= (*compar
)(vkey
, (*rootp
)->key
)) != 0) {
131 &(*rootp
)->llink
: /* follow llink branch */
132 &(*rootp
)->rlink
; /* follow rlink branch */
134 return NULL
; /* key not found */
136 r
= (*rootp
)->rlink
; /* D1: */
137 if ((q
= (*rootp
)->llink
) == NULL
) /* Left NULL? */
139 else if (r
!= NULL
) { /* Right link is NULL? */
140 if (r
->llink
== NULL
) { /* D2: Find successor */
143 } else { /* D3: Find NULL link */
144 for (q
= r
->llink
; q
->llink
!= NULL
; q
= r
->llink
)
147 q
->llink
= (*rootp
)->llink
;
148 q
->rlink
= (*rootp
)->rlink
;
151 free(*rootp
); /* D4: Free node */
152 *rootp
= q
; /* link parent to new node */
157 * find a node, or return 0
160 * vkey: key to be found
161 * vrootp: address of the tree root
163 ROKEN_LIB_FUNCTION
void *
164 rk_tfind(const void *vkey
, void * const *vrootp
,
165 int (*compar
)(const void *, const void *))
167 node_t
**rootp
= (node_t
**)vrootp
;
172 while (*rootp
!= NULL
) { /* T1: */
175 if ((r
= (*compar
)(vkey
, (*rootp
)->key
)) == 0) /* T2: */
176 return *rootp
; /* key found */
178 &(*rootp
)->llink
: /* T3: follow left branch */
179 &(*rootp
)->rlink
; /* T4: follow right branch */