2 * tree - balanced binary tree library
4 * vix 05apr94 [removed vixie.h dependencies; cleaned up formatting, names]
5 * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes]
6 * vix 23jun86 [added delete uar to add for replaced nodes]
7 * vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224]
8 * vix 06feb86 [added tree_mung()]
9 * vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221]
10 * vix 14dec85 [written]
14 * This program text was created by Paul Vixie using examples from the book:
15 * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN
16 * 0-13-022005-1. Any errors in the conversion from Modula-2 to C are Paul
21 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
22 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
24 * Permission to use, copy, modify, and distribute this software for any
25 * purpose with or without fee is hereby granted, provided that the above
26 * copyright notice and this permission notice appear in all copies.
28 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
29 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
30 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
31 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
32 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
33 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
34 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 /*#define DEBUG "tree"*/
39 #include "port_before.h"
44 #include "port_after.h"
46 #include <isc/memcluster.h>
50 static int debugDepth
= 0;
51 static char *debugFuncs
[256];
52 # define ENTER(proc) { \
53 debugFuncs[debugDepth] = proc; \
54 fprintf(stderr, "ENTER(%d:%s.%s)\n", \
56 debugFuncs[debugDepth]); \
59 # define RET(value) { \
61 fprintf(stderr, "RET(%d:%s.%s)\n", \
63 debugFuncs[debugDepth]); \
68 fprintf(stderr, "RETV(%d:%s.%s)\n", \
70 debugFuncs[debugDepth]); \
73 # define MSG(msg) fprintf(stderr, "MSG(%s)\n", msg);
75 # define ENTER(proc) ;
76 # define RET(value) return (value);
86 static tree
* sprout(tree
**, tree_t
, int *, int (*)(), void (*)());
87 static int delete(tree
**, int (*)(), tree_t
, void (*)(), int *, int *);
88 static void del(tree
**, int *, tree
**, void (*)(), int *);
89 static void bal_L(tree
**, int *);
90 static void bal_R(tree
**, int *);
93 tree_init(tree
**ppr_tree
) {
100 tree_srch(tree
**ppr_tree
, int (*pfi_compare
)(tree_t
, tree_t
), tree_t p_user
) {
104 int i_comp
= (*pfi_compare
)(p_user
, (**ppr_tree
).data
);
107 RET(tree_srch(&(**ppr_tree
).right
,
112 RET(tree_srch(&(**ppr_tree
).left
,
116 /* not higher, not lower... this must be the one.
118 RET((**ppr_tree
).data
)
121 /* grounded. NOT found.
127 tree_add(tree
**ppr_tree
, int (*pfi_compare
)(tree_t
, tree_t
),
128 tree_t p_user
, void (*pfv_uar
)())
130 int i_balance
= FALSE
;
133 if (!sprout(ppr_tree
, p_user
, &i_balance
, pfi_compare
, pfv_uar
))
139 tree_delete(tree
**ppr_p
, int (*pfi_compare
)(tree_t
, tree_t
),
140 tree_t p_user
, void (*pfv_uar
)())
142 int i_balance
= FALSE
, i_uar_called
= FALSE
;
144 ENTER("tree_delete");
145 RET(delete(ppr_p
, pfi_compare
, p_user
, pfv_uar
,
146 &i_balance
, &i_uar_called
))
150 tree_trav(tree
**ppr_tree
, int (*pfi_uar
)(tree_t
)) {
156 if (!tree_trav(&(**ppr_tree
).left
, pfi_uar
))
158 if (!(*pfi_uar
)((**ppr_tree
).data
))
160 if (!tree_trav(&(**ppr_tree
).right
, pfi_uar
))
166 tree_mung(tree
**ppr_tree
, void (*pfv_uar
)(tree_t
)) {
169 tree_mung(&(**ppr_tree
).left
, pfv_uar
);
170 tree_mung(&(**ppr_tree
).right
, pfv_uar
);
172 (*pfv_uar
)((**ppr_tree
).data
);
173 memput(*ppr_tree
, sizeof(tree
));
180 sprout(tree
**ppr
, tree_t p_data
, int *pi_balance
,
181 int (*pfi_compare
)(tree_t
, tree_t
), void (*pfv_delete
)(tree_t
))
188 /* are we grounded? if so, add the node "here" and set the rebalance
192 MSG("grounded. adding new node, setting h=true")
193 *ppr
= (tree
*) memget(sizeof(tree
));
196 (*ppr
)->right
= NULL
;
198 (*ppr
)->data
= p_data
;
204 /* compare the data using routine passed by caller.
206 cmp
= (*pfi_compare
)(p_data
, (*ppr
)->data
);
208 /* if LESS, prepare to move to the left.
211 MSG("LESS. sprouting left.")
212 sub
= sprout(&(*ppr
)->left
, p_data
, pi_balance
,
213 pfi_compare
, pfv_delete
);
214 if (sub
&& *pi_balance
) { /*%< left branch has grown */
215 MSG("LESS: left branch has grown")
216 switch ((*ppr
)->bal
) {
218 /* right branch WAS longer; bal is ok now */
219 MSG("LESS: case 1.. bal restored implicitly")
224 /* balance WAS okay; now left branch longer */
225 MSG("LESS: case 0.. balnce bad but still ok")
229 /* left branch was already too long. rebal */
230 MSG("LESS: case -1: rebalancing")
232 if (p1
->bal
== -1) { /*%< LL */
233 MSG("LESS: single LL")
234 (*ppr
)->left
= p1
->right
;
238 } else { /*%< double LR */
239 MSG("LESS: double LR")
242 p1
->right
= p2
->left
;
245 (*ppr
)->left
= p2
->right
;
266 /* if MORE, prepare to move to the right.
269 MSG("MORE: sprouting to the right")
270 sub
= sprout(&(*ppr
)->right
, p_data
, pi_balance
,
271 pfi_compare
, pfv_delete
);
272 if (sub
&& *pi_balance
) {
273 MSG("MORE: right branch has grown")
275 switch ((*ppr
)->bal
) {
277 MSG("MORE: balance was off, fixed implicitly")
282 MSG("MORE: balance was okay, now off but ok")
286 MSG("MORE: balance was off, need to rebalance")
288 if (p1
->bal
== 1) { /*%< RR */
289 MSG("MORE: single RR")
290 (*ppr
)->right
= p1
->left
;
294 } else { /*%< double RL */
295 MSG("MORE: double RL")
298 p1
->left
= p2
->right
;
301 (*ppr
)->right
= p2
->left
;
323 /* not less, not more: this is the same key! replace...
325 MSG("FOUND: Replacing data value")
328 (*pfv_delete
)((*ppr
)->data
);
329 (*ppr
)->data
= p_data
;
334 delete(tree
**ppr_p
, int (*pfi_compare
)(tree_t
, tree_t
), tree_t p_user
,
335 void (*pfv_uar
)(tree_t
), int *pi_balance
, int *pi_uar_called
)
342 if (*ppr_p
== NULL
) {
343 MSG("key not in tree")
347 i_comp
= (*pfi_compare
)((*ppr_p
)->data
, p_user
);
349 MSG("too high - scan left")
350 i_ret
= delete(&(*ppr_p
)->left
, pfi_compare
, p_user
, pfv_uar
,
351 pi_balance
, pi_uar_called
);
353 bal_L(ppr_p
, pi_balance
);
354 } else if (i_comp
< 0) {
355 MSG("too low - scan right")
356 i_ret
= delete(&(*ppr_p
)->right
, pfi_compare
, p_user
, pfv_uar
,
357 pi_balance
, pi_uar_called
);
359 bal_R(ppr_p
, pi_balance
);
363 if (pr_q
->right
== NULL
) {
364 MSG("right subtree null")
367 } else if (pr_q
->left
== NULL
) {
368 MSG("right subtree non-null, left subtree null")
369 *ppr_p
= pr_q
->right
;
372 MSG("neither subtree null")
373 del(&pr_q
->left
, pi_balance
, &pr_q
,
374 pfv_uar
, pi_uar_called
);
376 bal_L(ppr_p
, pi_balance
);
378 if (!*pi_uar_called
&& pfv_uar
)
379 (*pfv_uar
)(pr_q
->data
);
380 /* Thanks to wuth@castrov.cuc.ab.ca for the following stmt. */
381 memput(pr_q
, sizeof(tree
));
388 del(tree
**ppr_r
, int *pi_balance
, tree
**ppr_q
,
389 void (*pfv_uar
)(tree_t
), int *pi_uar_called
)
393 if ((*ppr_r
)->right
!= NULL
) {
394 del(&(*ppr_r
)->right
, pi_balance
, ppr_q
,
395 pfv_uar
, pi_uar_called
);
397 bal_R(ppr_r
, pi_balance
);
400 (*pfv_uar
)((*ppr_q
)->data
);
401 *pi_uar_called
= TRUE
;
402 (*ppr_q
)->data
= (*ppr_r
)->data
;
404 *ppr_r
= (*ppr_r
)->left
;
412 bal_L(tree
**ppr_p
, int *pi_balance
) {
417 MSG("left branch has shrunk")
419 switch ((*ppr_p
)->bal
) {
421 MSG("was imbalanced, fixed implicitly")
425 MSG("was okay, is now one off")
430 MSG("was already off, this is too much")
431 p1
= (*ppr_p
)->right
;
435 (*ppr_p
)->right
= p1
->left
;
452 p1
->left
= p2
->right
;
454 (*ppr_p
)->right
= p2
->left
;
472 bal_R(tree
**ppr_p
, int *pi_balance
) {
477 MSG("right branch has shrunk")
478 switch ((*ppr_p
)->bal
) {
480 MSG("was imbalanced, fixed implicitly")
484 MSG("was okay, is now one off")
489 MSG("was already off, this is too much")
494 (*ppr_p
)->left
= p1
->right
;
511 p1
->right
= p2
->left
;
513 (*ppr_p
)->left
= p2
->right
;