00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include "vixie.h"
00024 #include "tree.h"
00025 #ifdef DEBUG
00026 #undef DEBUG
00027 #endif
00028 #include "debug.h"
00029
00030 #ifdef __STDC__
00031 #define __P(x) x
00032 #else
00033 #define __P(x) ()
00034 #endif
00035
00036 static void sprout __P((tree **, tree_t, int *, int (*)(), void (*)()));
00037 static int delete __P((tree **, int (*)(), tree_t, void (*)(), int *,
00038
00039 int *));
00040 static void del __P((tree **, int *, tree **, void (*)(), int *));
00041 static void bal_L __P((tree **, int *));
00042 static void bal_R __P((tree **, int *));
00043
00044 #undef __P
00045
00046
00047 void tree_init(tree ** ppr_tree)
00048 {
00049 ENTER("tree_init");
00050 *ppr_tree = NULL;
00051 EXITV;
00052 }
00053
00054
00055 tree_t tree_srch(tree ** ppr_tree, int (*pfi_compare) ( ),
00056 tree_t p_user)
00057 {
00058 register int i_comp;
00059
00060 ENTER("tree_srch");
00061
00062 if (*ppr_tree) {
00063 i_comp = (*pfi_compare) (p_user, (**ppr_tree).tree_p);
00064 if (i_comp > 0)
00065 EXIT(tree_srch(&(**ppr_tree).tree_r, pfi_compare, p_user));
00066 if (i_comp < 0)
00067 EXIT(tree_srch(&(**ppr_tree).tree_l, pfi_compare, p_user));
00068
00069
00070
00071 EXIT((**ppr_tree).tree_p);
00072 }
00073
00074
00075
00076 EXIT(NULL);
00077 }
00078
00079
00080 void tree_add(tree ** ppr_tree, int (*pfi_compare) ( ),
00081 tree_t p_user, void (*pfv_uar) ( ))
00082 {
00083 int i_balance = FALSE;
00084
00085 ENTER("tree_add");
00086 sprout(ppr_tree, p_user, &i_balance, pfi_compare, pfv_uar);
00087 EXITV;
00088 }
00089
00090
00091 int tree_delete(tree ** ppr_p, int (*pfi_compare) ( ),
00092 tree_t p_user, void (*pfv_uar) ( ))
00093 {
00094 int i_balance = FALSE, i_uar_called = FALSE;
00095
00096 ENTER("tree_delete");
00097 EXIT(delete(ppr_p, pfi_compare, p_user, pfv_uar, &i_balance,
00098 &i_uar_called));
00099 } int tree_trav(tree ** ppr_tree, int (*pfi_uar) ( ))
00100 {
00101 ENTER("tree_trav");
00102
00103 if (!*ppr_tree)
00104 EXIT(TRUE);
00105
00106 if (!tree_trav(&(**ppr_tree).tree_l, pfi_uar))
00107 EXIT(FALSE);
00108 if (!(*pfi_uar) ((**ppr_tree).tree_p))
00109 EXIT(FALSE);
00110 if (!tree_trav(&(**ppr_tree).tree_r, pfi_uar))
00111 EXIT(FALSE);
00112 EXIT(TRUE);
00113 }
00114 void tree_mung(tree ** ppr_tree, void (*pfv_uar) ( ))
00115 {
00116 ENTER("tree_mung");
00117 if (*ppr_tree) {
00118 tree_mung(&(**ppr_tree).tree_l, pfv_uar);
00119 tree_mung(&(**ppr_tree).tree_r, pfv_uar);
00120 if (pfv_uar)
00121 (*pfv_uar) ((**ppr_tree).tree_p);
00122 free(*ppr_tree);
00123 *ppr_tree = NULL;
00124 }
00125 EXITV;
00126 }
00127
00128
00129 static void sprout(tree ** ppr, tree_t p_data, int *pi_balance,
00130 int (*pfi_compare) ( ),
00131 void (*pfv_delete) ( ))
00132 {
00133 tree *p1, *p2;
00134 int cmp;
00135
00136 ENTER("sprout");
00137
00138
00139
00140 if (!*ppr) {
00141 dprintk("grounded. adding new node, setting h=true");
00142 *ppr = (tree *) malloc(sizeof(tree));
00143 (*ppr)->tree_l = NULL;
00144 (*ppr)->tree_r = NULL;
00145 (*ppr)->tree_b = 0;
00146 (*ppr)->tree_p = p_data;
00147 *pi_balance = TRUE;
00148 EXITV;
00149 }
00150
00151
00152
00153 cmp = (*pfi_compare) (p_data, (*ppr)->tree_p);
00154
00155
00156
00157 if (cmp < 0) {
00158 dprintk("LESS. sprouting left.");
00159 sprout(&(*ppr)->tree_l, p_data, pi_balance, pfi_compare,
00160 pfv_delete);
00161 if (*pi_balance) {
00162 dprintk("LESS: left branch has grown");
00163 switch ((*ppr)->tree_b) {
00164 case 1:
00165 dprintk("LESS: case 1.. balnce restored implicitly");
00166 (*ppr)->tree_b = 0;
00167 *pi_balance = FALSE;
00168 break;
00169 case 0:
00170 dprintk("LESS: case 0.. balnce bad but still ok");
00171 (*ppr)->tree_b = -1;
00172 break;
00173 case -1:
00174
00175 dprintk("LESS: case -1: rebalancing");
00176 p1 = (*ppr)->tree_l;
00177 if (p1->tree_b == -1) {
00178 dprintk("LESS: single LL");
00179 (*ppr)->tree_l = p1->tree_r;
00180 p1->tree_r = *ppr;
00181 (*ppr)->tree_b = 0;
00182 *ppr = p1;
00183 } else {
00184 dprintk("LESS: double LR");
00185
00186 p2 = p1->tree_r;
00187 p1->tree_r = p2->tree_l;
00188 p2->tree_l = p1;
00189
00190 (*ppr)->tree_l = p2->tree_r;
00191 p2->tree_r = *ppr;
00192
00193 if (p2->tree_b == -1)
00194 (*ppr)->tree_b = 1;
00195 else
00196 (*ppr)->tree_b = 0;
00197
00198 if (p2->tree_b == 1)
00199 p1->tree_b = -1;
00200 else
00201 p1->tree_b = 0;
00202 *ppr = p2;
00203 }
00204 (*ppr)->tree_b = 0;
00205 *pi_balance = FALSE;
00206 }
00207 }
00208 EXITV;
00209 }
00210
00211
00212
00213
00214 if (cmp > 0) {
00215 dprintk("MORE: sprouting to the right");
00216 sprout(&(*ppr)->tree_r, p_data, pi_balance, pfi_compare,
00217 pfv_delete);
00218 if (*pi_balance) {
00219 dprintk("MORE: right branch has grown");
00220
00221 switch ((*ppr)->tree_b) {
00222 case -1:
00223 dprintk("MORE: balance was off, fixed implicitly");
00224 (*ppr)->tree_b = 0;
00225 *pi_balance = FALSE;
00226 break;
00227 case 0:
00228 dprintk("MORE: balance was okay, now off but ok");
00229 (*ppr)->tree_b = 1;
00230 break;
00231 case 1:
00232 dprintk("MORE: balance was off, need to rebalance");
00233 p1 = (*ppr)->tree_r;
00234 if (p1->tree_b == 1) {
00235 dprintk("MORE: single RR");
00236 (*ppr)->tree_r = p1->tree_l;
00237 p1->tree_l = *ppr;
00238 (*ppr)->tree_b = 0;
00239 *ppr = p1;
00240 } else {
00241 dprintk("MORE: double RL");
00242
00243 p2 = p1->tree_l;
00244 p1->tree_l = p2->tree_r;
00245 p2->tree_r = p1;
00246
00247 (*ppr)->tree_r = p2->tree_l;
00248 p2->tree_l = *ppr;
00249
00250 if (p2->tree_b == 1)
00251 (*ppr)->tree_b = -1;
00252 else
00253 (*ppr)->tree_b = 0;
00254
00255 if (p2->tree_b == -1)
00256 p1->tree_b = 1;
00257 else
00258 p1->tree_b = 0;
00259
00260 *ppr = p2;
00261 }
00262 (*ppr)->tree_b = 0;
00263 *pi_balance = FALSE;
00264 }
00265 }
00266 EXITV;
00267 }
00268
00269
00270
00271
00272 dprintk("I found it! Replacing data value");
00273 *pi_balance = FALSE;
00274 if (pfv_delete)
00275 (*pfv_delete) ((*ppr)->tree_p);
00276 (*ppr)->tree_p = p_data;
00277 EXITV;
00278 }
00279
00280
00281 static int delete(tree ** ppr_p, int (*pfi_compare) ( ),
00282 tree_t p_user, void (*pfv_uar) ( ),
00283 int *pi_balance, int *pi_uar_called)
00284 {
00285 tree *pr_q;
00286 int i_comp, i_ret;
00287
00288 ENTER("delete");
00289
00290 if (*ppr_p == NULL) {
00291 dprintk("key not in tree");
00292 EXIT(FALSE);
00293 }
00294
00295 i_comp = (*pfi_compare) ((*ppr_p)->tree_p, p_user);
00296
00297 if (i_comp > 0) {
00298 dprintk("too high - scan left");
00299 i_ret =
00300 delete(&(*ppr_p)->tree_l, pfi_compare, p_user, pfv_uar,
00301 pi_balance, pi_uar_called);
00302 if (*pi_balance)
00303 bal_L(ppr_p, pi_balance);
00304 } else if (i_comp < 0) {
00305 dprintk("too low - scan right");
00306 i_ret =
00307 delete(&(*ppr_p)->tree_r, pfi_compare, p_user, pfv_uar,
00308 pi_balance, pi_uar_called);
00309 if (*pi_balance)
00310 bal_R(ppr_p, pi_balance);
00311 } else {
00312 dprintk("equal");
00313 pr_q = *ppr_p;
00314 if (pr_q->tree_r == NULL) {
00315 dprintk("right subtree null");
00316 *ppr_p = pr_q->tree_l;
00317 *pi_balance = TRUE;
00318 } else if (pr_q->tree_l == NULL) {
00319 dprintk("right subtree non-null, left subtree null");
00320 *ppr_p = pr_q->tree_r;
00321 *pi_balance = TRUE;
00322 } else {
00323 dprintk("neither subtree null");
00324 del(&pr_q->tree_l, pi_balance, &pr_q, pfv_uar, pi_uar_called);
00325 if (*pi_balance)
00326 bal_L(ppr_p, pi_balance);
00327 }
00328 if (!*pi_uar_called && *pfv_uar)
00329 (*pfv_uar) (pr_q->tree_p);
00330 free(pr_q);
00331 i_ret = TRUE;
00332 }
00333 EXIT(i_ret);
00334 }
00335
00336
00337 static void del(tree ** ppr_r, int *pi_balance, tree ** ppr_q,
00338 void (*pfv_uar) ( ), int *pi_uar_called)
00339 {
00340 ENTER("del");
00341
00342 if ((*ppr_r)->tree_r != NULL) {
00343 del(&(*ppr_r)->tree_r, pi_balance, ppr_q, pfv_uar, pi_uar_called);
00344 if (*pi_balance)
00345 bal_R(ppr_r, pi_balance);
00346 } else {
00347 if (pfv_uar)
00348 (*pfv_uar) ((*ppr_q)->tree_p);
00349 *pi_uar_called = TRUE;
00350 (*ppr_q)->tree_p = (*ppr_r)->tree_p;
00351 *ppr_q = *ppr_r;
00352 *ppr_r = (*ppr_r)->tree_l;
00353 *pi_balance = TRUE;
00354 }
00355
00356 EXITV;
00357 }
00358
00359
00360 static void bal_L(tree ** ppr_p, int *pi_balance)
00361 {
00362 tree *p1, *p2;
00363 int b1, b2;
00364
00365 ENTER("bal_L");
00366 dprintk("left branch has shrunk");
00367
00368 switch ((*ppr_p)->tree_b) {
00369 case -1:
00370 dprintk("was imbalanced, fixed implicitly");
00371 (*ppr_p)->tree_b = 0;
00372 break;
00373 case 0:
00374 dprintk("was okay, is now one off");
00375 (*ppr_p)->tree_b = 1;
00376 *pi_balance = FALSE;
00377 break;
00378 case 1:
00379 dprintk("was already off, this is too much");
00380 p1 = (*ppr_p)->tree_r;
00381 b1 = p1->tree_b;
00382 if (b1 >= 0) {
00383 dprintk("single RR");
00384 (*ppr_p)->tree_r = p1->tree_l;
00385 p1->tree_l = *ppr_p;
00386 if (b1 == 0) {
00387 dprintk("b1 == 0");
00388 (*ppr_p)->tree_b = 1;
00389 p1->tree_b = -1;
00390 *pi_balance = FALSE;
00391 } else {
00392 dprintk("b1 != 0");
00393 (*ppr_p)->tree_b = 0;
00394 p1->tree_b = 0;
00395 }
00396 *ppr_p = p1;
00397 } else {
00398 dprintk("double RL");
00399 p2 = p1->tree_l;
00400 b2 = p2->tree_b;
00401 p1->tree_l = p2->tree_r;
00402 p2->tree_r = p1;
00403 (*ppr_p)->tree_r = p2->tree_l;
00404 p2->tree_l = *ppr_p;
00405 if (b2 == 1)
00406 (*ppr_p)->tree_b = -1;
00407 else
00408 (*ppr_p)->tree_b = 0;
00409 if (b2 == -1)
00410 p1->tree_b = 1;
00411 else
00412 p1->tree_b = 0;
00413 *ppr_p = p2;
00414 p2->tree_b = 0;
00415 }
00416 }
00417 EXITV;
00418 }
00419
00420
00421 static void bal_R(tree ** ppr_p, int *pi_balance)
00422 {
00423 tree *p1, *p2;
00424 int b1, b2;
00425
00426 ENTER("bal_R");
00427 dprintk("right branch has shrunk");
00428 switch ((*ppr_p)->tree_b) {
00429 case 1:
00430 dprintk("was imbalanced, fixed implicitly");
00431 (*ppr_p)->tree_b = 0;
00432 break;
00433 case 0:
00434 dprintk("was okay, is now one off");
00435 (*ppr_p)->tree_b = -1;
00436 *pi_balance = FALSE;
00437 break;
00438 case -1:
00439 dprintk("was already off, this is too much");
00440 p1 = (*ppr_p)->tree_l;
00441 b1 = p1->tree_b;
00442 if (b1 <= 0) {
00443 dprintk("single LL");
00444 (*ppr_p)->tree_l = p1->tree_r;
00445 p1->tree_r = *ppr_p;
00446 if (b1 == 0) {
00447 dprintk("b1 == 0");
00448 (*ppr_p)->tree_b = -1;
00449 p1->tree_b = 1;
00450 *pi_balance = FALSE;
00451 } else {
00452 dprintk("b1 != 0");
00453 (*ppr_p)->tree_b = 0;
00454 p1->tree_b = 0;
00455 }
00456 *ppr_p = p1;
00457 } else {
00458 dprintk("double LR");
00459 p2 = p1->tree_r;
00460 b2 = p2->tree_b;
00461 p1->tree_r = p2->tree_l;
00462 p2->tree_l = p1;
00463 (*ppr_p)->tree_l = p2->tree_r;
00464 p2->tree_r = *ppr_p;
00465 if (b2 == -1)
00466 (*ppr_p)->tree_b = 1;
00467 else
00468 (*ppr_p)->tree_b = 0;
00469 if (b2 == 1)
00470 p1->tree_b = -1;
00471 else
00472 p1->tree_b = 0;
00473 *ppr_p = p2;
00474 p2->tree_b = 0;
00475 }
00476 }
00477 EXITV;
00478 }