ptree.c
Go to the documentation of this file.
00001 #include "../stdafx.h"
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <assert.h>
00006 #include "ptree.h"
00007 
00008 //#define VERIFY_TREE
00009 
00010 struct ptree_node {
00011         void *pn_value;
00012         struct ptree_node *pn_parent;
00013         struct ptree_node *pn_left;
00014         struct ptree_node *pn_right;
00015 };
00016 
00017 static int
00018 _walk_to(void *v, 
00019                  struct ptree_node **startp, 
00020                  struct ptree_node ***pp,
00021                  int (*cmp)(const void *v1, const void *v2))
00022 {
00023         struct ptree_node **nextp;
00024         int c = -1;
00025 
00026         nextp = startp;
00027         while (*nextp)
00028         {
00029                 c = cmp(v, (*nextp)->pn_value);
00030                 *startp = *nextp;
00031                 if (c == 0)
00032                         break;
00033                 if (c < 0)
00034                         nextp = &(*nextp)->pn_left;
00035                 else
00036                         nextp = &(*nextp)->pn_right;
00037                 if (pp)
00038                         *pp = nextp;
00039         }
00040 
00041         return c;
00042 }
00043 
00044 
00045 static ptree_walk_res_t
00046 _visit(struct ptree_node *pn, 
00047            int level, 
00048            void *arg1, 
00049            void *arg2)
00050 {
00051         ptree_walk_res_t (*func)(const void *, int, void *, void *) = arg1;
00052         
00053         return func(pn->pn_value, level, arg2, pn);
00054 }
00055 
00056 static ptree_node_t *
00057 _find_min(ptree_node_t *pn, 
00058                   int *levelp)
00059 {
00060         while (pn->pn_left)
00061         {
00062                 pn = pn->pn_left;
00063                 if (levelp)
00064                         (*levelp)++;
00065         }
00066         return pn;
00067 }
00068 
00069 static ptree_node_t *
00070 _find_succ(ptree_node_t *pn, 
00071                    int *levelp)
00072 {
00073         if (pn->pn_right)
00074         {
00075                 pn = pn->pn_right;
00076                 if (levelp)
00077                         (*levelp)++;
00078                 while (pn->pn_left)
00079                 {
00080                         pn = pn->pn_left;
00081                         if (levelp)
00082                                 (*levelp)++;
00083                 }
00084         }
00085         else
00086         {
00087                 while (pn->pn_parent && pn->pn_parent->pn_right == pn)
00088                 {
00089                         pn = pn->pn_parent;
00090                         if (levelp)
00091                                 (*levelp)--;
00092                 }
00093                 pn = pn->pn_parent;
00094                 if (levelp)
00095                         (*levelp)--;
00096         }
00097                 
00098         return pn;
00099 }
00100 
00101 static int
00102 _walk_int(struct ptree_node *pn, 
00103                   ptree_order_t order, 
00104                   int level,
00105                   ptree_walk_res_t (*func)(struct ptree_node *, int level, void *, void *),
00106                   void *arg1, 
00107                   void *arg2)
00108 {
00109         ptree_walk_res_t res;
00110         ptree_node_t *next;
00111 
00112         if (!pn)
00113                 return PTREE_WALK_CONTINUE;
00114 
00115         if (order == PTREE_INORDER)
00116         {
00117                 int nlevel;
00118 
00119                 pn = _find_min(pn, &level);
00120                 while (pn) 
00121                 {
00122                         nlevel = level;
00123                         next = _find_succ(pn, &nlevel);
00124                         if ((res = func(pn, level, arg1, arg2)) != PTREE_WALK_CONTINUE)
00125                                 return res;
00126                         level = nlevel;
00127                         if (level < 0)
00128                                 level = 0;
00129                         pn = next;
00130                 }
00131                 return PTREE_WALK_CONTINUE;
00132         }
00133         if (order == PTREE_PREORDER && (res = func(pn, level, arg1, arg2)) != PTREE_WALK_CONTINUE)
00134                 return res;
00135         if ((res = _walk_int(pn->pn_left, order, level + 1, func, arg1, arg2)) != PTREE_WALK_CONTINUE)
00136                 return res;
00137         if ((res = _walk_int(pn->pn_right, order, level + 1, func, arg1, arg2)) != PTREE_WALK_CONTINUE)
00138                 return res;
00139         if (order == PTREE_POSTORDER && (res = func(pn, level, arg1, arg2)) != PTREE_WALK_CONTINUE)
00140                 return res;
00141         return PTREE_WALK_CONTINUE;
00142 }
00143 
00144 #ifdef VERIFY_TREE
00145 static ptree_walk_res_t
00146 _count(struct ptree_node *pn, 
00147            int level, 
00148            void *arg1, 
00149            void *arg2)
00150 {
00151         int *counter = arg1;
00152         (*counter)++;
00153         return PTREE_WALK_CONTINUE;
00154 }
00155 
00156 //counts the number of nodes
00157 static int
00158 _count_nodes(ptree_node_t **rootp)
00159 {
00160         int counter = 0;
00161         _walk_int(*rootp, PTREE_INORDER, 0, _count, &counter, 0);
00162         return counter; 
00163 }
00164 
00165 static ptree_walk_res_t
00166 _verify_node(struct ptree_node *pn, 
00167            int level, 
00168            void *arg1, 
00169            void *arg2)
00170 {
00171         int (*cmp)(const void *v1, const void *v2) = arg1;
00172         struct ptree_node **prev_pn_p = (struct ptree_node **)arg2;
00173         struct ptree_node *prev_pn = *prev_pn_p;
00174         
00175         if(pn->pn_left != NULL && pn->pn_left->pn_parent != pn)
00176                 return PTREE_WALK_STOP;
00177         if(pn->pn_right != NULL && pn->pn_right->pn_parent != pn)
00178                 return PTREE_WALK_STOP;
00179 
00180         if(prev_pn != NULL)
00181         {
00182                 //this value should always be greater then the last value
00183                 if(cmp(pn->pn_value, prev_pn->pn_value) <= 0)
00184                         return PTREE_WALK_STOP;
00185         }
00186         *prev_pn_p = pn;
00187                    
00188    return PTREE_WALK_CONTINUE;
00189 }
00190 
00191 //static int
00192 //pdecmp(const void *sv, const void *dv)
00193 //{
00194 //      int res;
00195 //      
00196 //      char *str1 = *(char **)sv;
00197 //      char *str2 = *(char **)dv;
00198 //      
00199 //      res = strcmp(str1, str2);
00200 //      
00201 //      if(res <= 0)
00202 //              return res;
00203 //      
00204 //      return res;
00205 //}
00206 
00207 //Verifies that the tree is a valid Binary search tree
00208 static int
00209 _verify_tree(ptree_node_t **rootp, int (*cmp)(const void *v1, const void *v2))
00210 {
00211         struct ptree_node *prev_pn = NULL;
00212         if(_walk_int(*rootp, PTREE_INORDER, 0, _verify_node, cmp, &prev_pn) == PTREE_WALK_STOP)
00213                 return 0;
00214         return 1;
00215 }
00216 #endif
00217 
00218 static void
00219 _remove_node(ptree_node_t **rootp, 
00220                          ptree_node_t *pn, 
00221                          void **oldval)
00222 {
00223         ptree_node_t **pp;
00224         ptree_node_t **predp;
00225         ptree_node_t *pred;
00226         
00227 #ifdef VERIFY_TREE
00228         int countStart = _count_nodes(rootp), countEnd=0;
00229 #endif
00230 
00231         //Find pn in the tree
00232         if (!pn->pn_parent)
00233         {
00234                 assert(rootp && pn == *rootp);
00235                 pp = rootp;
00236         }
00237         else
00238         {
00239                 if (pn->pn_parent->pn_left == pn)
00240                         pp = &pn->pn_parent->pn_left;
00241                 else
00242                         pp = &pn->pn_parent->pn_right;
00243         }
00244         
00245         //pp should now point at the location where pn is stored in the tree
00246         assert(pp);
00247         
00248         //Best case - only one child, on no children, just remove as in a list
00249         if (!pn->pn_left)
00250         {
00251                 *pp = pn->pn_right;
00252                 if (pn->pn_right)
00253                         pn->pn_right->pn_parent = pn->pn_parent;
00254         }
00255         else if (!pn->pn_right)
00256         {
00257                 *pp = pn->pn_left;
00258                 if (pn->pn_left)
00259                         pn->pn_left->pn_parent = pn->pn_parent;
00260         }
00261 
00262         //Worst case: pn contains both left and right children
00263         else 
00264         {
00265                 for (predp = &pn->pn_left; (*predp)->pn_right; )
00266                         predp = &(*predp)->pn_right;
00267                 pred = *predp;
00268 
00269                 //pred either has a left child or no child
00270                 if (pred->pn_parent->pn_left == pred)
00271                         pred->pn_parent->pn_left = pred->pn_left;
00272                 else
00273                         pred->pn_parent->pn_right = pred->pn_left;
00274                 if(pred->pn_left)
00275                         pred->pn_left->pn_parent = pred->pn_parent;
00276 
00277                 *pp = pred;
00278 
00279                 pred->pn_parent = pn->pn_parent;
00280                 pred->pn_left = pn->pn_left;
00281                 pred->pn_right = pn->pn_right;
00282 
00283                 if (pn->pn_left)
00284                         pn->pn_left->pn_parent = pred;
00285                 pn->pn_right->pn_parent = pred;
00286         }
00287 
00288         //Return the value of the removed node
00289         if (oldval)
00290                 *oldval = pn->pn_value;
00291 
00292         free(pn);
00293         
00294 #ifdef VERIFY_TREE
00295         countEnd = _count_nodes(rootp);
00296         countStart--;
00297         assert(countEnd == countStart);
00298 #endif
00299 }
00300 
00301 int
00302 ptree_inorder_walk_remove(ptree_node_t **rootp, 
00303                                                   void **oldval, 
00304                                                   void *pn,
00305                                                   int (*cmp)(const void *v1, const void *v2))
00306 {
00307         assert(pn);
00308         if (!pn)
00309                 return 0;
00310 #ifdef VERIFY_TREE
00311         assert(_verify_tree(rootp, cmp));
00312 #endif
00313         _remove_node(rootp, pn, oldval);
00314 #ifdef VERIFY_TREE
00315         assert(_verify_tree(rootp, cmp));
00316 #endif
00317         return 1;
00318 }
00319 
00320 ptree_walk_res_t
00321 ptree_walk(ptree_node_t *start, 
00322                    ptree_order_t order,
00323                    ptree_walk_res_t (*func)(const void *v1, int level, void *arg, void *ptree_inorder_walking_remove_arg), 
00324                    int (*cmp)(const void *v1, const void *v2),
00325                    void *arg)
00326 {
00327 #ifdef VERIFY_TREE
00328         ptree_node_t *start_p = start;
00329         if(cmp != NULL)
00330                 assert(_verify_tree(&start_p, cmp));
00331 #endif
00332 
00333         return _walk_int((struct ptree_node *)start, order, 0, _visit, (void *)func, arg);
00334 }
00335 
00336 ptree_walk_res_t
00337 ptree_clear_func(struct ptree_node *pn, 
00338                                  int level, 
00339                                  void *arg1, 
00340                                  void *arg2)
00341 {
00342         free(pn); pn = NULL;
00343 
00344         return PTREE_WALK_CONTINUE;
00345 }
00346 
00347 void
00348 ptree_clear(ptree_node_t **rootp)
00349 {
00350         _walk_int(*rootp, PTREE_POSTORDER, 0, ptree_clear_func, 0, 0);
00351         *rootp = 0;
00352 }
00353 
00354 int
00355 ptree_remove(void *v, 
00356                          ptree_node_t **rootp, 
00357                          int (*cmp)(const void *v1, const void *v2), 
00358                          void **oldval)
00359 {
00360         struct ptree_node *cur;
00361         
00362 #ifdef VERIFY_TREE
00363         assert(_verify_tree(rootp, cmp));
00364 #endif
00365 
00366         cur = *rootp;
00367         if (_walk_to(v, &cur, NULL, cmp) != 0)
00368                 return 0;
00369         _remove_node(rootp, cur, oldval);
00370         
00371 #ifdef VERIFY_TREE
00372         assert(_verify_tree(rootp, cmp));
00373 #endif
00374 
00375         return 1;
00376 }
00377 
00378 int
00379 ptree_replace(void *v, 
00380                           ptree_node_t **rootp, 
00381                           int (*cmp)(const void *v1, const void *v2), 
00382                           void **oldval)
00383 {
00384         struct ptree_node **parentpp;
00385         struct ptree_node *parentp;
00386         struct ptree_node *pn;
00387         int c;
00388         
00389 #ifdef VERIFY_TREE
00390         int countStart = _count_nodes(rootp), countEnd=0;
00391 #endif
00392         
00393         parentp = *rootp;
00394         parentpp = rootp;
00395         
00396 #ifdef VERIFY_TREE
00397         assert(_verify_tree(rootp, cmp));
00398 #endif
00399 
00400         //if we find v in the tree, replace it
00401         if ((c = _walk_to(v, &parentp, &parentpp, cmp)) == 0)
00402         {
00403                 if (oldval)
00404                         *oldval = parentp->pn_value;
00405                 parentp->pn_value = v;
00406         
00407 #ifdef VERIFY_TREE
00408         assert(_verify_tree(rootp, cmp));
00409 #endif
00410         
00411 #ifdef VERIFY_TREE
00412         countEnd = _count_nodes(rootp);
00413         assert(countEnd == countStart);
00414 #endif
00415                 
00416                 return 1;
00417         }
00418         
00419         //otherwise, add it to the tree
00420         if (!(pn = malloc(sizeof (*pn))))
00421                 return 0;
00422         
00423         memset(pn, 0, sizeof (*pn));
00424         pn->pn_value = v;
00425         pn->pn_parent = parentp;
00426         *parentpp = pn;
00427         if (oldval)
00428                 *oldval = 0;
00429         
00430 #ifdef VERIFY_TREE
00431         assert(_verify_tree(rootp, cmp));
00432 #endif
00433         
00434 #ifdef VERIFY_TREE
00435         countEnd = _count_nodes(rootp);
00436         countStart++;
00437         assert(countEnd == countStart);
00438 #endif
00439 
00440         return 1;
00441 }
00442 
00443 int
00444 ptree_contains(void *v, 
00445                            ptree_node_t *parentp, 
00446                            int (*cmp)(const void *v1, const void *v2), 
00447                            void **nodeval)
00448 {
00449         int c;
00450 
00451         if ((c = _walk_to(v, &parentp, NULL, cmp)) == 0)
00452         {
00453                 if (nodeval)
00454                         *nodeval = parentp->pn_value;
00455                 return 1;
00456         }
00457         if (nodeval)
00458                 *nodeval = 0;
00459         return 0;
00460 }


pedal_monitor
Author(s): Pedro Mendes
autogenerated on Fri Jun 6 2014 18:37:21