Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / bind / isc / tree.c
blobb308b1cdab9969c2d27336233dddfa466bbed6f5
1 #ifndef LINT
2 static const char rcsid[] = "$Id: tree.c,v 1.2.2.1 2004/03/09 09:17:36 marka Exp $";
3 #endif
5 /*
6 * tree - balanced binary tree library
8 * vix 05apr94 [removed vixie.h dependencies; cleaned up formatting, names]
9 * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes]
10 * vix 23jun86 [added delete uar to add for replaced nodes]
11 * vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224]
12 * vix 06feb86 [added tree_mung()]
13 * vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221]
14 * vix 14dec85 [written]
18 * This program text was created by Paul Vixie using examples from the book:
19 * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN
20 * 0-13-022005-1. Any errors in the conversion from Modula-2 to C are Paul
21 * Vixie's.
25 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
26 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
28 * Permission to use, copy, modify, and distribute this software for any
29 * purpose with or without fee is hereby granted, provided that the above
30 * copyright notice and this permission notice appear in all copies.
32 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
33 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
35 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
36 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
37 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
38 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41 /*#define DEBUG "tree"*/
43 #include "port_before.h"
45 #include <stdio.h>
46 #include <stdlib.h>
48 #include "port_after.h"
50 #include <isc/memcluster.h>
51 #include <isc/tree.h>
53 #ifdef DEBUG
54 static int debugDepth = 0;
55 static char *debugFuncs[256];
56 # define ENTER(proc) { \
57 debugFuncs[debugDepth] = proc; \
58 fprintf(stderr, "ENTER(%d:%s.%s)\n", \
59 debugDepth, DEBUG, \
60 debugFuncs[debugDepth]); \
61 debugDepth++; \
63 # define RET(value) { \
64 debugDepth--; \
65 fprintf(stderr, "RET(%d:%s.%s)\n", \
66 debugDepth, DEBUG, \
67 debugFuncs[debugDepth]); \
68 return (value); \
70 # define RETV { \
71 debugDepth--; \
72 fprintf(stderr, "RETV(%d:%s.%s)\n", \
73 debugDepth, DEBUG, \
74 debugFuncs[debugDepth]); \
75 return; \
77 # define MSG(msg) fprintf(stderr, "MSG(%s)\n", msg);
78 #else
79 # define ENTER(proc) ;
80 # define RET(value) return (value);
81 # define RETV return;
82 # define MSG(msg) ;
83 #endif
85 #ifndef TRUE
86 # define TRUE 1
87 # define FALSE 0
88 #endif
90 static tree * sprout(tree **, tree_t, int *, int (*)(), void (*)());
91 static int delete(tree **, int (*)(), tree_t, void (*)(), int *, int *);
92 static void del(tree **, int *, tree **, void (*)(), int *);
93 static void bal_L(tree **, int *);
94 static void bal_R(tree **, int *);
96 void
97 tree_init(tree **ppr_tree) {
98 ENTER("tree_init")
99 *ppr_tree = NULL;
100 RETV
103 tree_t
104 tree_srch(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t), tree_t p_user) {
105 ENTER("tree_srch")
107 if (*ppr_tree) {
108 int i_comp = (*pfi_compare)(p_user, (**ppr_tree).data);
110 if (i_comp > 0)
111 RET(tree_srch(&(**ppr_tree).right,
112 pfi_compare,
113 p_user))
115 if (i_comp < 0)
116 RET(tree_srch(&(**ppr_tree).left,
117 pfi_compare,
118 p_user))
120 /* not higher, not lower... this must be the one.
122 RET((**ppr_tree).data)
125 /* grounded. NOT found.
127 RET(NULL)
130 tree_t
131 tree_add(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t),
132 tree_t p_user, void (*pfv_uar)())
134 int i_balance = FALSE;
136 ENTER("tree_add")
137 if (!sprout(ppr_tree, p_user, &i_balance, pfi_compare, pfv_uar))
138 RET(NULL)
139 RET(p_user)
143 tree_delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t),
144 tree_t p_user, void (*pfv_uar)())
146 int i_balance = FALSE, i_uar_called = FALSE;
148 ENTER("tree_delete");
149 RET(delete(ppr_p, pfi_compare, p_user, pfv_uar,
150 &i_balance, &i_uar_called))
154 tree_trav(tree **ppr_tree, int (*pfi_uar)(tree_t)) {
155 ENTER("tree_trav")
157 if (!*ppr_tree)
158 RET(TRUE)
160 if (!tree_trav(&(**ppr_tree).left, pfi_uar))
161 RET(FALSE)
162 if (!(*pfi_uar)((**ppr_tree).data))
163 RET(FALSE)
164 if (!tree_trav(&(**ppr_tree).right, pfi_uar))
165 RET(FALSE)
166 RET(TRUE)
169 void
170 tree_mung(tree **ppr_tree, void (*pfv_uar)(tree_t)) {
171 ENTER("tree_mung")
172 if (*ppr_tree) {
173 tree_mung(&(**ppr_tree).left, pfv_uar);
174 tree_mung(&(**ppr_tree).right, pfv_uar);
175 if (pfv_uar)
176 (*pfv_uar)((**ppr_tree).data);
177 memput(*ppr_tree, sizeof(tree));
178 *ppr_tree = NULL;
180 RETV
183 static tree *
184 sprout(tree **ppr, tree_t p_data, int *pi_balance,
185 int (*pfi_compare)(tree_t, tree_t), void (*pfv_delete)(tree_t))
187 tree *p1, *p2, *sub;
188 int cmp;
190 ENTER("sprout")
192 /* are we grounded? if so, add the node "here" and set the rebalance
193 * flag, then exit.
195 if (!*ppr) {
196 MSG("grounded. adding new node, setting h=true")
197 *ppr = (tree *) memget(sizeof(tree));
198 if (*ppr) {
199 (*ppr)->left = NULL;
200 (*ppr)->right = NULL;
201 (*ppr)->bal = 0;
202 (*ppr)->data = p_data;
203 *pi_balance = TRUE;
205 RET(*ppr);
208 /* compare the data using routine passed by caller.
210 cmp = (*pfi_compare)(p_data, (*ppr)->data);
212 /* if LESS, prepare to move to the left.
214 if (cmp < 0) {
215 MSG("LESS. sprouting left.")
216 sub = sprout(&(*ppr)->left, p_data, pi_balance,
217 pfi_compare, pfv_delete);
218 if (sub && *pi_balance) { /* left branch has grown */
219 MSG("LESS: left branch has grown")
220 switch ((*ppr)->bal) {
221 case 1:
222 /* right branch WAS longer; bal is ok now */
223 MSG("LESS: case 1.. bal restored implicitly")
224 (*ppr)->bal = 0;
225 *pi_balance = FALSE;
226 break;
227 case 0:
228 /* balance WAS okay; now left branch longer */
229 MSG("LESS: case 0.. balnce bad but still ok")
230 (*ppr)->bal = -1;
231 break;
232 case -1:
233 /* left branch was already too long. rebal */
234 MSG("LESS: case -1: rebalancing")
235 p1 = (*ppr)->left;
236 if (p1->bal == -1) { /* LL */
237 MSG("LESS: single LL")
238 (*ppr)->left = p1->right;
239 p1->right = *ppr;
240 (*ppr)->bal = 0;
241 *ppr = p1;
242 } else { /* double LR */
243 MSG("LESS: double LR")
245 p2 = p1->right;
246 p1->right = p2->left;
247 p2->left = p1;
249 (*ppr)->left = p2->right;
250 p2->right = *ppr;
252 if (p2->bal == -1)
253 (*ppr)->bal = 1;
254 else
255 (*ppr)->bal = 0;
257 if (p2->bal == 1)
258 p1->bal = -1;
259 else
260 p1->bal = 0;
261 *ppr = p2;
262 } /*else*/
263 (*ppr)->bal = 0;
264 *pi_balance = FALSE;
265 } /*switch*/
266 } /*if*/
267 RET(sub)
268 } /*if*/
270 /* if MORE, prepare to move to the right.
272 if (cmp > 0) {
273 MSG("MORE: sprouting to the right")
274 sub = sprout(&(*ppr)->right, p_data, pi_balance,
275 pfi_compare, pfv_delete);
276 if (sub && *pi_balance) {
277 MSG("MORE: right branch has grown")
279 switch ((*ppr)->bal) {
280 case -1:
281 MSG("MORE: balance was off, fixed implicitly")
282 (*ppr)->bal = 0;
283 *pi_balance = FALSE;
284 break;
285 case 0:
286 MSG("MORE: balance was okay, now off but ok")
287 (*ppr)->bal = 1;
288 break;
289 case 1:
290 MSG("MORE: balance was off, need to rebalance")
291 p1 = (*ppr)->right;
292 if (p1->bal == 1) { /* RR */
293 MSG("MORE: single RR")
294 (*ppr)->right = p1->left;
295 p1->left = *ppr;
296 (*ppr)->bal = 0;
297 *ppr = p1;
298 } else { /* double RL */
299 MSG("MORE: double RL")
301 p2 = p1->left;
302 p1->left = p2->right;
303 p2->right = p1;
305 (*ppr)->right = p2->left;
306 p2->left = *ppr;
308 if (p2->bal == 1)
309 (*ppr)->bal = -1;
310 else
311 (*ppr)->bal = 0;
313 if (p2->bal == -1)
314 p1->bal = 1;
315 else
316 p1->bal = 0;
318 *ppr = p2;
319 } /*else*/
320 (*ppr)->bal = 0;
321 *pi_balance = FALSE;
322 } /*switch*/
323 } /*if*/
324 RET(sub)
325 } /*if*/
327 /* not less, not more: this is the same key! replace...
329 MSG("FOUND: Replacing data value")
330 *pi_balance = FALSE;
331 if (pfv_delete)
332 (*pfv_delete)((*ppr)->data);
333 (*ppr)->data = p_data;
334 RET(*ppr)
337 static int
338 delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t), tree_t p_user,
339 void (*pfv_uar)(tree_t), int *pi_balance, int *pi_uar_called)
341 tree *pr_q;
342 int i_comp, i_ret;
344 ENTER("delete")
346 if (*ppr_p == NULL) {
347 MSG("key not in tree")
348 RET(FALSE)
351 i_comp = (*pfi_compare)((*ppr_p)->data, p_user);
352 if (i_comp > 0) {
353 MSG("too high - scan left")
354 i_ret = delete(&(*ppr_p)->left, pfi_compare, p_user, pfv_uar,
355 pi_balance, pi_uar_called);
356 if (*pi_balance)
357 bal_L(ppr_p, pi_balance);
358 } else if (i_comp < 0) {
359 MSG("too low - scan right")
360 i_ret = delete(&(*ppr_p)->right, pfi_compare, p_user, pfv_uar,
361 pi_balance, pi_uar_called);
362 if (*pi_balance)
363 bal_R(ppr_p, pi_balance);
364 } else {
365 MSG("equal")
366 pr_q = *ppr_p;
367 if (pr_q->right == NULL) {
368 MSG("right subtree null")
369 *ppr_p = pr_q->left;
370 *pi_balance = TRUE;
371 } else if (pr_q->left == NULL) {
372 MSG("right subtree non-null, left subtree null")
373 *ppr_p = pr_q->right;
374 *pi_balance = TRUE;
375 } else {
376 MSG("neither subtree null")
377 del(&pr_q->left, pi_balance, &pr_q,
378 pfv_uar, pi_uar_called);
379 if (*pi_balance)
380 bal_L(ppr_p, pi_balance);
382 if (!*pi_uar_called && pfv_uar)
383 (*pfv_uar)(pr_q->data);
384 /* Thanks to wuth@castrov.cuc.ab.ca for the following stmt. */
385 memput(pr_q, sizeof(tree));
386 i_ret = TRUE;
388 RET(i_ret)
391 static void
392 del(tree **ppr_r, int *pi_balance, tree **ppr_q,
393 void (*pfv_uar)(tree_t), int *pi_uar_called)
395 ENTER("del")
397 if ((*ppr_r)->right != NULL) {
398 del(&(*ppr_r)->right, pi_balance, ppr_q,
399 pfv_uar, pi_uar_called);
400 if (*pi_balance)
401 bal_R(ppr_r, pi_balance);
402 } else {
403 if (pfv_uar)
404 (*pfv_uar)((*ppr_q)->data);
405 *pi_uar_called = TRUE;
406 (*ppr_q)->data = (*ppr_r)->data;
407 *ppr_q = *ppr_r;
408 *ppr_r = (*ppr_r)->left;
409 *pi_balance = TRUE;
412 RETV
415 static void
416 bal_L(tree **ppr_p, int *pi_balance) {
417 tree *p1, *p2;
418 int b1, b2;
420 ENTER("bal_L")
421 MSG("left branch has shrunk")
423 switch ((*ppr_p)->bal) {
424 case -1:
425 MSG("was imbalanced, fixed implicitly")
426 (*ppr_p)->bal = 0;
427 break;
428 case 0:
429 MSG("was okay, is now one off")
430 (*ppr_p)->bal = 1;
431 *pi_balance = FALSE;
432 break;
433 case 1:
434 MSG("was already off, this is too much")
435 p1 = (*ppr_p)->right;
436 b1 = p1->bal;
437 if (b1 >= 0) {
438 MSG("single RR")
439 (*ppr_p)->right = p1->left;
440 p1->left = *ppr_p;
441 if (b1 == 0) {
442 MSG("b1 == 0")
443 (*ppr_p)->bal = 1;
444 p1->bal = -1;
445 *pi_balance = FALSE;
446 } else {
447 MSG("b1 != 0")
448 (*ppr_p)->bal = 0;
449 p1->bal = 0;
451 *ppr_p = p1;
452 } else {
453 MSG("double RL")
454 p2 = p1->left;
455 b2 = p2->bal;
456 p1->left = p2->right;
457 p2->right = p1;
458 (*ppr_p)->right = p2->left;
459 p2->left = *ppr_p;
460 if (b2 == 1)
461 (*ppr_p)->bal = -1;
462 else
463 (*ppr_p)->bal = 0;
464 if (b2 == -1)
465 p1->bal = 1;
466 else
467 p1->bal = 0;
468 *ppr_p = p2;
469 p2->bal = 0;
472 RETV
475 static void
476 bal_R(tree **ppr_p, int *pi_balance) {
477 tree *p1, *p2;
478 int b1, b2;
480 ENTER("bal_R")
481 MSG("right branch has shrunk")
482 switch ((*ppr_p)->bal) {
483 case 1:
484 MSG("was imbalanced, fixed implicitly")
485 (*ppr_p)->bal = 0;
486 break;
487 case 0:
488 MSG("was okay, is now one off")
489 (*ppr_p)->bal = -1;
490 *pi_balance = FALSE;
491 break;
492 case -1:
493 MSG("was already off, this is too much")
494 p1 = (*ppr_p)->left;
495 b1 = p1->bal;
496 if (b1 <= 0) {
497 MSG("single LL")
498 (*ppr_p)->left = p1->right;
499 p1->right = *ppr_p;
500 if (b1 == 0) {
501 MSG("b1 == 0")
502 (*ppr_p)->bal = -1;
503 p1->bal = 1;
504 *pi_balance = FALSE;
505 } else {
506 MSG("b1 != 0")
507 (*ppr_p)->bal = 0;
508 p1->bal = 0;
510 *ppr_p = p1;
511 } else {
512 MSG("double LR")
513 p2 = p1->right;
514 b2 = p2->bal;
515 p1->right = p2->left;
516 p2->left = p1;
517 (*ppr_p)->left = p2->right;
518 p2->right = *ppr_p;
519 if (b2 == -1)
520 (*ppr_p)->bal = 1;
521 else
522 (*ppr_p)->bal = 0;
523 if (b2 == 1)
524 p1->bal = -1;
525 else
526 p1->bal = 0;
527 *ppr_p = p2;
528 p2->bal = 0;
531 RETV