1*ae771770SStanislav Sedov /*
2*ae771770SStanislav Sedov * Tree search generalized from Knuth (6.2.2) Algorithm T just like
3*ae771770SStanislav Sedov * the AT&T man page says.
4*ae771770SStanislav Sedov *
5*ae771770SStanislav Sedov * The node_t structure is for internal use only, lint doesn't grok it.
6*ae771770SStanislav Sedov *
7*ae771770SStanislav Sedov * Written by reading the System V Interface Definition, not the code.
8*ae771770SStanislav Sedov *
9*ae771770SStanislav Sedov * Totally public domain.
10*ae771770SStanislav Sedov *
11*ae771770SStanislav Sedov * $NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $
12*ae771770SStanislav Sedov * $NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp $
13*ae771770SStanislav Sedov * $NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $
14*ae771770SStanislav Sedov * $NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $
15*ae771770SStanislav Sedov */
16*ae771770SStanislav Sedov
17*ae771770SStanislav Sedov #include <config.h>
18*ae771770SStanislav Sedov #include "roken.h"
19*ae771770SStanislav Sedov #include "search.h"
20*ae771770SStanislav Sedov #include <stdlib.h>
21*ae771770SStanislav Sedov
22*ae771770SStanislav Sedov typedef struct node {
23*ae771770SStanislav Sedov char *key;
24*ae771770SStanislav Sedov struct node *llink, *rlink;
25*ae771770SStanislav Sedov } node_t;
26*ae771770SStanislav Sedov
27*ae771770SStanislav Sedov #ifndef __DECONST
28*ae771770SStanislav Sedov #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
29*ae771770SStanislav Sedov #endif
30*ae771770SStanislav Sedov
31*ae771770SStanislav Sedov /*
32*ae771770SStanislav Sedov * find or insert datum into search tree
33*ae771770SStanislav Sedov *
34*ae771770SStanislav Sedov * Parameters:
35*ae771770SStanislav Sedov * vkey: key to be located
36*ae771770SStanislav Sedov * vrootp: address of tree root
37*ae771770SStanislav Sedov */
38*ae771770SStanislav Sedov
39*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void *
rk_tsearch(const void * vkey,void ** vrootp,int (* compar)(const void *,const void *))40*ae771770SStanislav Sedov rk_tsearch(const void *vkey, void **vrootp,
41*ae771770SStanislav Sedov int (*compar)(const void *, const void *))
42*ae771770SStanislav Sedov {
43*ae771770SStanislav Sedov node_t *q;
44*ae771770SStanislav Sedov node_t **rootp = (node_t **)vrootp;
45*ae771770SStanislav Sedov
46*ae771770SStanislav Sedov if (rootp == NULL)
47*ae771770SStanislav Sedov return NULL;
48*ae771770SStanislav Sedov
49*ae771770SStanislav Sedov while (*rootp != NULL) { /* Knuth's T1: */
50*ae771770SStanislav Sedov int r;
51*ae771770SStanislav Sedov
52*ae771770SStanislav Sedov if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */
53*ae771770SStanislav Sedov return *rootp; /* we found it! */
54*ae771770SStanislav Sedov
55*ae771770SStanislav Sedov rootp = (r < 0) ?
56*ae771770SStanislav Sedov &(*rootp)->llink : /* T3: follow left branch */
57*ae771770SStanislav Sedov &(*rootp)->rlink; /* T4: follow right branch */
58*ae771770SStanislav Sedov }
59*ae771770SStanislav Sedov
60*ae771770SStanislav Sedov q = malloc(sizeof(node_t)); /* T5: key not found */
61*ae771770SStanislav Sedov if (q != 0) { /* make new node */
62*ae771770SStanislav Sedov *rootp = q; /* link new node to old */
63*ae771770SStanislav Sedov /* LINTED const castaway ok */
64*ae771770SStanislav Sedov q->key = __DECONST(void *, vkey); /* initialize new node */
65*ae771770SStanislav Sedov q->llink = q->rlink = NULL;
66*ae771770SStanislav Sedov }
67*ae771770SStanislav Sedov return q;
68*ae771770SStanislav Sedov }
69*ae771770SStanislav Sedov
70*ae771770SStanislav Sedov /*
71*ae771770SStanislav Sedov * Walk the nodes of a tree
72*ae771770SStanislav Sedov *
73*ae771770SStanislav Sedov * Parameters:
74*ae771770SStanislav Sedov * root: Root of the tree to be walked
75*ae771770SStanislav Sedov */
76*ae771770SStanislav Sedov static void
trecurse(const node_t * root,void (* action)(const void *,VISIT,int),int level)77*ae771770SStanislav Sedov trecurse(const node_t *root, void (*action)(const void *, VISIT, int),
78*ae771770SStanislav Sedov int level)
79*ae771770SStanislav Sedov {
80*ae771770SStanislav Sedov
81*ae771770SStanislav Sedov if (root->llink == NULL && root->rlink == NULL)
82*ae771770SStanislav Sedov (*action)(root, leaf, level);
83*ae771770SStanislav Sedov else {
84*ae771770SStanislav Sedov (*action)(root, preorder, level);
85*ae771770SStanislav Sedov if (root->llink != NULL)
86*ae771770SStanislav Sedov trecurse(root->llink, action, level + 1);
87*ae771770SStanislav Sedov (*action)(root, postorder, level);
88*ae771770SStanislav Sedov if (root->rlink != NULL)
89*ae771770SStanislav Sedov trecurse(root->rlink, action, level + 1);
90*ae771770SStanislav Sedov (*action)(root, endorder, level);
91*ae771770SStanislav Sedov }
92*ae771770SStanislav Sedov }
93*ae771770SStanislav Sedov
94*ae771770SStanislav Sedov /*
95*ae771770SStanislav Sedov * Walk the nodes of a tree
96*ae771770SStanislav Sedov *
97*ae771770SStanislav Sedov * Parameters:
98*ae771770SStanislav Sedov * vroot: Root of the tree to be walked
99*ae771770SStanislav Sedov */
100*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void
rk_twalk(const void * vroot,void (* action)(const void *,VISIT,int))101*ae771770SStanislav Sedov rk_twalk(const void *vroot,
102*ae771770SStanislav Sedov void (*action)(const void *, VISIT, int))
103*ae771770SStanislav Sedov {
104*ae771770SStanislav Sedov if (vroot != NULL && action != NULL)
105*ae771770SStanislav Sedov trecurse(vroot, action, 0);
106*ae771770SStanislav Sedov }
107*ae771770SStanislav Sedov
108*ae771770SStanislav Sedov /*
109*ae771770SStanislav Sedov * delete node with given key
110*ae771770SStanislav Sedov *
111*ae771770SStanislav Sedov * vkey: key to be deleted
112*ae771770SStanislav Sedov * vrootp: address of the root of the tree
113*ae771770SStanislav Sedov * compar: function to carry out node comparisons
114*ae771770SStanislav Sedov */
115*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void *
rk_tdelete(const void * vkey,void ** vrootp,int (* compar)(const void *,const void *))116*ae771770SStanislav Sedov rk_tdelete(const void * vkey, void ** vrootp,
117*ae771770SStanislav Sedov int (*compar)(const void *, const void *))
118*ae771770SStanislav Sedov {
119*ae771770SStanislav Sedov node_t **rootp = (node_t **)vrootp;
120*ae771770SStanislav Sedov node_t *p, *q, *r;
121*ae771770SStanislav Sedov int cmp;
122*ae771770SStanislav Sedov
123*ae771770SStanislav Sedov if (rootp == NULL || (p = *rootp) == NULL)
124*ae771770SStanislav Sedov return NULL;
125*ae771770SStanislav Sedov
126*ae771770SStanislav Sedov while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) {
127*ae771770SStanislav Sedov p = *rootp;
128*ae771770SStanislav Sedov rootp = (cmp < 0) ?
129*ae771770SStanislav Sedov &(*rootp)->llink : /* follow llink branch */
130*ae771770SStanislav Sedov &(*rootp)->rlink; /* follow rlink branch */
131*ae771770SStanislav Sedov if (*rootp == NULL)
132*ae771770SStanislav Sedov return NULL; /* key not found */
133*ae771770SStanislav Sedov }
134*ae771770SStanislav Sedov r = (*rootp)->rlink; /* D1: */
135*ae771770SStanislav Sedov if ((q = (*rootp)->llink) == NULL) /* Left NULL? */
136*ae771770SStanislav Sedov q = r;
137*ae771770SStanislav Sedov else if (r != NULL) { /* Right link is NULL? */
138*ae771770SStanislav Sedov if (r->llink == NULL) { /* D2: Find successor */
139*ae771770SStanislav Sedov r->llink = q;
140*ae771770SStanislav Sedov q = r;
141*ae771770SStanislav Sedov } else { /* D3: Find NULL link */
142*ae771770SStanislav Sedov for (q = r->llink; q->llink != NULL; q = r->llink)
143*ae771770SStanislav Sedov r = q;
144*ae771770SStanislav Sedov r->llink = q->rlink;
145*ae771770SStanislav Sedov q->llink = (*rootp)->llink;
146*ae771770SStanislav Sedov q->rlink = (*rootp)->rlink;
147*ae771770SStanislav Sedov }
148*ae771770SStanislav Sedov }
149*ae771770SStanislav Sedov free(*rootp); /* D4: Free node */
150*ae771770SStanislav Sedov *rootp = q; /* link parent to new node */
151*ae771770SStanislav Sedov return p;
152*ae771770SStanislav Sedov }
153*ae771770SStanislav Sedov
154*ae771770SStanislav Sedov /*
155*ae771770SStanislav Sedov * find a node, or return 0
156*ae771770SStanislav Sedov *
157*ae771770SStanislav Sedov * Parameters:
158*ae771770SStanislav Sedov * vkey: key to be found
159*ae771770SStanislav Sedov * vrootp: address of the tree root
160*ae771770SStanislav Sedov */
161*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void *
rk_tfind(const void * vkey,void * const * vrootp,int (* compar)(const void *,const void *))162*ae771770SStanislav Sedov rk_tfind(const void *vkey, void * const *vrootp,
163*ae771770SStanislav Sedov int (*compar)(const void *, const void *))
164*ae771770SStanislav Sedov {
165*ae771770SStanislav Sedov node_t **rootp = (node_t **)vrootp;
166*ae771770SStanislav Sedov
167*ae771770SStanislav Sedov if (rootp == NULL)
168*ae771770SStanislav Sedov return NULL;
169*ae771770SStanislav Sedov
170*ae771770SStanislav Sedov while (*rootp != NULL) { /* T1: */
171*ae771770SStanislav Sedov int r;
172*ae771770SStanislav Sedov
173*ae771770SStanislav Sedov if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */
174*ae771770SStanislav Sedov return *rootp; /* key found */
175*ae771770SStanislav Sedov rootp = (r < 0) ?
176*ae771770SStanislav Sedov &(*rootp)->llink : /* T3: follow left branch */
177*ae771770SStanislav Sedov &(*rootp)->rlink; /* T4: follow right branch */
178*ae771770SStanislav Sedov }
179*ae771770SStanislav Sedov return NULL;
180*ae771770SStanislav Sedov }
181