1 /* Copyright (C) 1994 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
20 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
21 * the AT&T man page says.
23 * The node_t structure is for internal use only, lint doesn't grok it.
25 * Written by reading the System V Interface Definition, not the code.
27 * Totally public domain.
34 /* This routine is not very bad. It makes many assumptions about
35 * the compiler. It assumpts that the first field in node must be
36 * the "key" field, which points to the datum. It is a very trick
43 struct node_t *left, *right;
47 /* find or insert datum into search tree.
48 char *key; key to be located
49 register node **rootp; address of tree root
50 int (*compar)(); ordering function
53 libc_hidden_proto(tsearch)
54 void *tsearch(__const void *key, void **vrootp, __compar_fn_t compar)
57 register node **rootp = (node **) vrootp;
59 if (rootp == (struct node_t **)0)
60 return ((struct node_t *)0);
61 while (*rootp != (struct node_t *)0) /* Knuth's T1: */
65 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
66 return (*rootp); /* we found it! */
68 &(*rootp)->left : /* T3: follow left branch */
69 &(*rootp)->right; /* T4: follow right branch */
71 q = (node *) malloc(sizeof(node)); /* T5: key not found */
72 if (q != (struct node_t *)0) /* make new node */
74 *rootp = q; /* link new node to old */
75 q->key = (void *)key; /* initialize new node */
76 q->left = q->right = (struct node_t *)0;
80 libc_hidden_def(tsearch)
84 libc_hidden_proto(tfind)
85 void *tfind(__const void *key, void * __const *vrootp, __compar_fn_t compar)
87 register node **rootp = (node **) vrootp;
89 if (rootp == (struct node_t **)0)
90 return ((struct node_t *)0);
91 while (*rootp != (struct node_t *)0) /* Knuth's T1: */
95 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
96 return (*rootp); /* we found it! */
98 &(*rootp)->left : /* T3: follow left branch */
99 &(*rootp)->right; /* T4: follow right branch */
103 libc_hidden_def(tfind)
107 /* delete node with given key
108 char *key; key to be deleted
109 register node **rootp; address of the root of tree
110 int (*compar)(); comparison function
112 void *tdelete(__const void *key, void ** vrootp, __compar_fn_t compar)
118 register node **rootp = (node **) vrootp;
120 if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0)
121 return ((struct node_t *)0);
122 while ((cmp = (*compar)(key, (*rootp)->key)) != 0)
126 &(*rootp)->left : /* follow left branch */
127 &(*rootp)->right; /* follow right branch */
128 if (*rootp == (struct node_t *)0)
129 return ((struct node_t *)0); /* key not found */
131 r = (*rootp)->right; /* D1: */
132 if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */
134 else if (r != (struct node_t *)0) /* Right link is null? */
136 if (r->left == (struct node_t *)0) /* D2: Find successor */
142 { /* D3: Find (struct node_t *)0 link */
143 for (q = r->left; q->left != (struct node_t *)0; q = r->left)
146 q->left = (*rootp)->left;
147 q->right = (*rootp)->right;
150 free((struct node_t *) *rootp); /* D4: Free node */
151 *rootp = q; /* link parent to new node */
157 /* Walk the nodes of a tree
158 register node *root; Root of the tree to be walked
159 register void (*action)(); Function to be called at each node
162 static void trecurse(__const void *vroot, __action_fn_t action, int level)
164 register node *root = (node *) vroot;
166 if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
167 (*action)(root, leaf, level);
170 (*action)(root, preorder, level);
171 if (root->left != (struct node_t *)0)
172 trecurse(root->left, action, level + 1);
173 (*action)(root, postorder, level);
174 if (root->right != (struct node_t *)0)
175 trecurse(root->right, action, level + 1);
176 (*action)(root, endorder, level);
180 /* void twalk(root, action) Walk the nodes of a tree
181 node *root; Root of the tree to be walked
182 void (*action)(); Function to be called at each node
185 void twalk(__const void *vroot, __action_fn_t action)
187 register __const node *root = (node *) vroot;
189 if (root != (node *)0 && action != (__action_fn_t) 0)
190 trecurse(root, action, 0);
196 /* The standardized functions miss an important functionality: the
197 tree cannot be removed easily. We provide a function to do this. */
200 tdestroy_recurse (node *root, __free_fn_t freefct)
202 if (root->left != NULL)
203 tdestroy_recurse (root->left, freefct);
204 if (root->right != NULL)
205 tdestroy_recurse (root->right, freefct);
206 (*freefct) ((void *) root->key);
207 /* Free the node itself. */
211 libc_hidden_proto(tdestroy)
212 void tdestroy (void *vroot, __free_fn_t freefct)
214 node *root = (node *) vroot;
216 tdestroy_recurse (root, freefct);
219 libc_hidden_def(tdestroy)
223 /* tsearch.c ends here */