tree/tree.c

Go to the documentation of this file.
00001 
00002 /* as_tree - tree library for as
00003  * vix 14dec85 [written]
00004  * vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221]
00005  * vix 06feb86 [added tree_mung()]
00006  * vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224]
00007  * vix 23jun86 [added delete uar to add for replaced nodes]
00008  * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes]
00009  */
00010 
00011 
00012 /* This program text was created by Paul Vixie using examples from the book:
00013  * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN
00014  * 0-13-022005-1.  This code and associated documentation is hereby placed
00015  * in the public domain.
00016  */
00017 
00018 /*#define               DEBUG   "tree"*/
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         /* not higher, not lower... this must be the one.
00070          */
00071         EXIT((**ppr_tree).tree_p);
00072     }
00073 
00074     /* grounded. NOT found.
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     /* are we grounded?  if so, add the node "here" and set the rebalance
00139      * flag, then exit.
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     /* compare the data using routine passed by caller.
00152      */
00153     cmp = (*pfi_compare) (p_data, (*ppr)->tree_p);
00154 
00155     /* if LESS, prepare to move to the left.
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) {      /* left branch has grown longer */
00162             dprintk("LESS: left branch has grown");
00163             switch ((*ppr)->tree_b) {
00164             case 1:             /* right branch WAS longer; balance is ok now */
00165                 dprintk("LESS: case 1.. balnce restored implicitly");
00166                     (*ppr)->tree_b = 0;
00167                 *pi_balance = FALSE;
00168                 break;
00169             case 0:             /* balance WAS okay; now left branch longer */
00170                 dprintk("LESS: case 0.. balnce bad but still ok");
00171                 (*ppr)->tree_b = -1;
00172                 break;
00173             case -1:
00174                 /* left branch was already too long. rebalnce */
00175                 dprintk("LESS: case -1: rebalancing");
00176                 p1 = (*ppr)->tree_l;
00177                 if (p1->tree_b == -1) { /* LL */
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 {        /* double LR */
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                 }               /*else */
00204                 (*ppr)->tree_b = 0;
00205                 *pi_balance = FALSE;
00206             }                   /*switch */
00207         }                       /*if */
00208         EXITV;
00209     }
00210 
00211     /*if */
00212     /* if MORE, prepare to move to the right.
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) {      /* right branch has grown longer */
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) {  /* RR */
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 {        /* double RL */
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                 }               /*else */
00262                 (*ppr)->tree_b = 0;
00263                 *pi_balance = FALSE;
00264             }                   /*switch */
00265         }                       /*if */
00266         EXITV;
00267     }
00268 
00269     /*if */
00270     /* not less, not more: this is the same key!  replace...
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);             /* thanks to wuth@castrov.cuc.ab.ca */
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 }

Generated on Mon May 28 04:25:26 2007 for BattletechMUX by  doxygen 1.4.7