Simple data structures / objects in plain C Snapshot
tree.h
Go to the documentation of this file.
00001 /* Copyright (c) Michael Moser (2011) . 3-clause BSD License applies */
00002 
00003 #ifndef _VTREE_H_
00004 #define _VTREE_H_
00005 
00006 #ifdef  __cplusplus
00007 extern "C" {
00008 #endif
00009 
00010 
00011 #include <cutils/base.h>
00012 
00013 
00014 #define TREE_NEXTLEVEL_LAST 
00015 #define TREE_NEXTLEVEL_LEFT
00016 
00017 /**
00018  * @defgroup TREE
00019  * @brief a tree.
00020  * tree. Each node has variable number of child nodes, the node is embeddable (like ring list).
00021  * This tree is especially suited for parse trees.
00022  * @{
00023  */
00024 typedef struct tagTREENODE {
00025         struct tagTREENODE *parent;
00026         
00027         struct tagTREENODE *nextlevel_first;
00028 #ifdef TREE_NEXTLEVEL_LAST
00029         struct tagTREENODE *nextlevel_last;
00030 #endif
00031         struct tagTREENODE *right;
00032 #ifdef TREE_NEXTLEVEL_LEFT      
00033         struct tagTREENODE *left;
00034 #endif
00035 } TREENODE;
00036 
00037 M_INLINE void TREE_init_root(TREENODE *tree)
00038 {
00039         tree->right = tree->parent = tree->nextlevel_first = 0;
00040 #ifdef TREE_NEXTLEVEL_LEFT
00041         tree->left = 0;
00042 #endif
00043 #ifdef TREE_NEXTLEVEL_LAST
00044         tree->nextlevel_last = 0;
00045 #endif
00046 }
00047 
00048 M_INLINE TREENODE *TREE_parent(TREENODE *node)
00049 {
00050         return node->parent;
00051 }
00052 
00053 
00054 M_INLINE TREENODE *TREE_left_sibling(TREENODE *node)
00055 {
00056 #ifdef TREE_NEXTLEVEL_LEFT
00057         return node->left;
00058 #else
00059         TREENODE *tmp;
00060 
00061         if (!node->parent) {
00062                 return 0;
00063         }
00064         tmp = node->parent->nextlevel_first;
00065         if (tmp == node) {
00066                 return 0;
00067         }
00068         while(tmp && tmp->right != node) {
00069                 tmp = tmp->right;
00070         }
00071         return tmp;
00072 #endif
00073 }
00074 
00075 M_INLINE TREENODE *TREE_right_sibling(TREENODE *node)
00076 {
00077         return node->right;
00078 }
00079 
00080 M_INLINE TREENODE *TREE_leftmost_sibling(TREENODE *node)
00081 {
00082         TREENODE *parent = node->parent;
00083         if (parent) {
00084                 return parent->nextlevel_first;
00085         }
00086         return 0;
00087 }
00088 
00089 M_INLINE TREENODE *TREE_rightmost_sibling(TREENODE *node)
00090 {
00091 #ifdef TREE_NEXTLEVEL_LAST
00092         TREENODE *parent = node->parent;
00093         if (parent) {
00094                 return parent->nextlevel_last;
00095         }
00096         return 0;
00097 #else
00098         while(node->right) {
00099                 node = node->right;
00100         }
00101 #endif
00102         return node;
00103 }
00104 
00105 M_INLINE TREENODE *TREE_first_child(TREENODE *node)
00106 {
00107         return node->nextlevel_first;
00108 }
00109 
00110 M_INLINE TREENODE *TREE_last_child(TREENODE *node)
00111 {
00112 #ifdef TREE_NEXTLEVEL_LAST
00113         return node->nextlevel_last;
00114 #else
00115         return TREE_rightmost_sibling(node->nextlevel_first);
00116 #endif
00117 }
00118 
00119 
00120 
00121 /* insert function -> new element next level is initialised hereby to zero ? option? new function? */
00122 
00123 M_INLINE int TREE_insert_right_sibling(TREENODE *current, TREENODE *newnode, int node_is_leaf)
00124 {
00125         TREENODE *parent = current->parent;
00126 
00127         if (!parent) {
00128                 return -1;
00129         }
00130         if (node_is_leaf) {
00131                 TREE_init_root(newnode);
00132         }
00133 
00134 #ifdef TREE_NEXTLEVEL_LAST
00135         if (parent->nextlevel_last == current) {
00136                 parent->nextlevel_last = newnode;
00137         }
00138 #endif
00139 
00140         newnode->parent = parent;
00141         
00142 #ifdef TREE_NEXTLEVEL_LEFT
00143         newnode->left  = current;
00144         if (current->right) {
00145                 current->right->left = newnode;
00146         }
00147 #endif
00148         newnode->right = current->right;
00149         current->right = newnode;
00150 
00151 
00152 
00153         return 0;
00154 }
00155 
00156 
00157 M_INLINE int TREE_insert_left_sibling(TREENODE *current, TREENODE *newnode, int node_is_leaf)
00158 {
00159         TREENODE *parent = current->parent;
00160         if (!parent) {
00161                 return -1;
00162         }
00163 
00164         if (node_is_leaf) {
00165                 TREE_init_root(newnode);
00166         }
00167 
00168         if (parent->nextlevel_first == current) {
00169                 parent->nextlevel_first = newnode;
00170         }
00171 
00172         newnode->parent = parent;
00173 
00174 #ifdef TREE_NEXTLEVEL_LEFT
00175         if (current->left) {
00176                 current->left->right = newnode;
00177         }
00178 #endif
00179         newnode->right = current;
00180 #ifdef TREE_NEXTLEVEL_LEFT      
00181         newnode->left = current->left;
00182         current->left = newnode;
00183 #endif
00184 
00185 
00186 
00187         return 0;
00188 }
00189 
00190 typedef enum {
00191   TREE_INSERT_FIRST,
00192   TREE_INSERT_LAST,
00193 
00194 } TREE_INSERT_MODE;
00195 
00196 M_INLINE void TREE_insert_child(TREENODE *parent, TREENODE *newnode, TREE_INSERT_MODE mode, int node_is_leaf )
00197 {       
00198         /* init new node */
00199         if (node_is_leaf) {
00200                 newnode->nextlevel_first = 0;
00201 #ifdef TREE_NEXTLEVEL_LAST
00202                 newnode->nextlevel_last = 0;
00203 #endif
00204         }
00205         newnode->parent = parent;
00206         newnode->right = 0;
00207 #ifdef TREE_NEXTLEVEL_LEFT
00208         newnode->left = 0;
00209 #endif  
00210 
00211         
00212         if (!parent->nextlevel_first) {         
00213 
00214                 /* insert as first child */
00215                 //newnode->nextlevel_first = parent->nextlevel_first;
00216                 parent->nextlevel_first = newnode;
00217 #ifdef TREE_NEXTLEVEL_LAST
00218                 //newnode->nextlevel_last = parent->nextlevel_last;
00219                 parent->nextlevel_last = newnode;
00220 #endif
00221                 
00222         } else {
00223 
00224                 /* insert as sibling */
00225                 switch(mode) {
00226                         case TREE_INSERT_FIRST: {
00227                                         TREE_insert_left_sibling(parent->nextlevel_first,newnode, 0);
00228                                 }
00229                                 break;
00230                         case TREE_INSERT_LAST:
00231 #ifdef TREE_NEXTLEVEL_LAST
00232                                 TREE_insert_right_sibling( parent->nextlevel_last,newnode, 0);
00233 #else
00234                                 TREE_insert_right_sibling( TREE_rightmost_sibling(parent->nextlevel_first), newnode, 0);
00235 #endif
00236 
00237                                 break;
00238                 }
00239         }
00240 
00241 }
00242 
00243 
00244 M_INLINE void TREE_merge_childs(TREENODE *parent, TREE_INSERT_MODE mode, TREENODE *newnode)
00245 {       
00246         TREENODE *ch;
00247 
00248         switch(mode) {
00249 
00250         case TREE_INSERT_LAST:  
00251                 ch = TREE_first_child(newnode);
00252                 if (!ch) {
00253                         return;
00254                 }
00255 
00256                 while(ch) {
00257                         TREE_insert_child(parent, ch, TREE_INSERT_LAST, 0 );
00258                         ch = TREE_right_sibling(ch);
00259                 }
00260                 break;
00261 
00262         case TREE_INSERT_FIRST: 
00263                 ch = TREE_last_child(newnode);
00264                 if (!ch) {
00265                         return;
00266                 }
00267 
00268                 while(ch) {
00269                         TREE_insert_child(parent, ch, TREE_INSERT_FIRST, 0 );
00270                         ch = TREE_left_sibling(ch);
00271                 }
00272                 break;
00273         }
00274 }
00275 
00276 
00277 M_INLINE TREENODE * TREE_unlink_node(TREENODE *node)
00278 {
00279         TREENODE *tmp,*tmp_next, *tmp_last;
00280 
00281         if (!node->parent) {
00282                 return 0;
00283         }
00284 
00285         /* wrong */
00286         tmp = node->parent;
00287         if (tmp && tmp->nextlevel_first == node) {
00288 
00289                 if (!node->nextlevel_first) {
00290                         tmp->nextlevel_first = node->right;
00291                         goto sdel;
00292                 }
00293 
00294                 tmp->nextlevel_first = node->nextlevel_first;                           
00295                 tmp_next = tmp->nextlevel_first;
00296                 tmp_last = TREE_rightmost_sibling(tmp_next);
00297 
00298                 tmp_last->right = node->right;
00299 #ifdef TREE_NEXTLEVEL_LEFT
00300                 if (node->right) {
00301                         node->right->left = tmp_last;
00302                 }
00303 #endif
00304                 do {
00305                         tmp_next->parent = tmp;
00306                         if (tmp_next == tmp_last) {
00307                                 break;
00308                         }
00309                         tmp_next = tmp_next->right;
00310                 } while(tmp_next);
00311 
00312                 return node;
00313         }
00314 
00315 #ifdef TREE_NEXTLEVEL_LAST
00316         if (tmp && tmp->nextlevel_last == node) {
00317 
00318                 if (!node->nextlevel_last) {
00319                         tmp->nextlevel_last = TREE_left_sibling(node);
00320                         goto sdel;
00321                 }
00322 
00323                 tmp->nextlevel_last = node->nextlevel_last;     
00324                 tmp_next = tmp->nextlevel_last;
00325                 tmp_last = TREE_leftmost_sibling(tmp_next);
00326 
00327 #ifdef TREE_NEXTLEVEL_LEFT
00328                 tmp_last->left = node->left;
00329 #endif
00330                 TREE_left_sibling(node)->right = tmp_last;
00331 
00332                 do {
00333                         tmp_last->parent = tmp;
00334                         if (tmp_next == tmp_last) {
00335                                 break;
00336                         }
00337                         tmp_last = tmp_last->right;
00338                 } while(tmp_last);                                      
00339 
00340                 return node;
00341         }
00342 #endif
00343 
00344 sdel:
00345 
00346 #ifdef TREE_NEXTLEVEL_LEFT
00347         tmp = node->right;
00348         if (tmp) {
00349                 tmp->left = node->left;
00350         }
00351 #endif
00352 
00353         tmp = TREE_left_sibling(node);
00354         if (tmp) {
00355                 tmp->right = node->right;
00356         }
00357 
00358         return node;
00359 }
00360 
00361 
00362 typedef int  (*TREE_VISITOR) (TREENODE *entry, void *context);
00363 typedef void  (*TREE_VISITOR_V) (TREENODE *entry, void *context);
00364 
00365 typedef enum {
00366   TREE_PREORDER,
00367   TREE_POSTORDER,
00368 
00369 } TREE_VISIT_EVENT;
00370 
00371 typedef int  (*TREE_VISITOR_EXT_V) (TREENODE *entry, TREE_VISIT_EVENT visit, void *context);
00372 
00373 
00374 #define TREE_FOREACH_CHILD(current, node) \
00375         for((current) = TREE_first_child(node); \
00376                 (current); \
00377                 (current) = TREE_right_sibling(current)) 
00378 
00379 #define TREE_FOREACH_CHILD_REVERSE(current, node) \
00380         for((current) = TREE_last_child(node); \
00381                 (current); \
00382                 (current) = TREE_left_sibling(current)) 
00383 
00384 
00385 M_INLINE size_t TREE_count_child_nodes( TREENODE *current)
00386 {
00387         size_t ret = 0;
00388         TREENODE *c;
00389 
00390         TREE_FOREACH_CHILD(c,current) {
00391                 ret++;
00392         }
00393         return ret;
00394 }
00395 
00396 /*
00397  a
00398  |
00399  b-d-g
00400  | |
00401  c e-f
00402 */
00403 M_INLINE TREENODE *TREE_preorder_next(TREENODE *current)
00404 {
00405         if (current->nextlevel_first) {
00406                 current = current->nextlevel_first;
00407         } else {
00408                 if (current->right) {
00409                         current = current->right;
00410                 } else {
00411                         while(current->parent) {
00412                                 current = current->parent;
00413                                 if (current->right) {
00414                                         current = current->right;
00415                                         break;
00416                                 }
00417                         }
00418                 }
00419         }
00420 
00421         return current;
00422 }
00423 
00424 #if 0
00425 M_INLINE TREENODE *TREE_preorder_next_ext(TREENODE *current, TREE_VISITOR_EXT_V ext, void *context)
00426 {
00427         if (current->nextlevel_first) {
00428                 current = current->nextlevel_first;
00429         } else {
00430                 if (current->right) {
00431                         current = current->right;
00432                 } else {
00433                         while(current->parent) {
00434 
00435                                 ext( context, TREE_POSTORDER, context);
00436 
00437                                 current = current->parent;
00438                                 if (current->right) {
00439                                         current = current->right;
00440                                         break;
00441                                 }
00442                         }
00443                 }
00444         }
00445 
00446         return current;
00447 }
00448 #endif
00449 
00450 
00451 /**
00452  * @brief iterate over all elements of a list of child nodes, callback is invoked for either element of the list. list is traversed from first element to the last element.
00453  * @param lst (in) node in a tree (parent of enumerated childs).
00454  * @param eval (in) callback that is called to visit each set (or cleared) bit.
00455  * @param context (in) pointer that is passed as context on each invocation of callback.
00456  * @param save_from_del (in) if non zero then callback can remove the current link from the list (a bit slower); if null then not; if zero then can't remove the current link from the list.
00457  */
00458 M_INLINE void TREE_foreach_child( TREENODE *lst, TREE_VISITOR_V eval, void *context)
00459 {
00460     TREENODE *cur;
00461 
00462         if (!eval) {
00463           return;
00464         }
00465 
00466         TREE_FOREACH_CHILD( cur, lst) {
00467                 eval( cur, context );
00468         }
00469         
00470 }
00471 
00472 
00473 
00474 M_INLINE void TREE_foreach_child_reverse( TREENODE *lst, TREE_VISITOR_V eval, void *context)
00475 {
00476     TREENODE *cur;
00477 
00478         if (!eval) {
00479           return;
00480         }
00481 
00482 
00483         TREE_FOREACH_CHILD_REVERSE( cur,lst) {
00484                 eval( cur, context );
00485         }
00486         
00487 }
00488 
00489 /**
00490  * @brief find an element within the list of child nodes. callback is invoked for each element of the list, in forward direction from first element to last element; when the callback returns non zero value the iteration stops as we have found what we searched for.
00491  * 
00492  * @param tree (in) node in a tree (parent of enumerated childs).
00493  * @param eval (in) callback that is called to visit each set (or cleared) bit.
00494  * @param context (in) pointer that is passed as context on each invocation of callback.
00495  * @param retval (out) optional - the first non zero value returned by eval callback, if NULL then ignored.
00496  * @return the list element that has matched (i.e. element that has been found).
00497  *
00498  */
00499 M_INLINE TREENODE * TREE_findif_child( TREENODE *tree, TREE_VISITOR eval, void *context, int32_t *retval)
00500 {
00501         int ret;
00502     TREENODE *cur;
00503 
00504         if (retval) {
00505                 *retval = 0;
00506         }
00507 
00508         if (!eval) {
00509                 return 0;
00510         }
00511         
00512 
00513         TREE_FOREACH_CHILD( cur, tree) {
00514                 ret = eval( cur, context );
00515                 if (ret) {
00516                         if (retval) {
00517                                 *retval = ret;
00518                         }
00519                         return cur;
00520                 }
00521         }
00522 
00523         return 0;
00524 }
00525 
00526 M_INLINE TREENODE * TREE_findif_child_reverse( TREENODE *tree, TREE_VISITOR eval, void *context, int32_t *retval)
00527 {
00528         int ret;
00529     TREENODE *cur;
00530 
00531         if (retval) {
00532                 *retval = 0;
00533         }
00534 
00535         if (!eval) {
00536                 return 0;
00537         }
00538         
00539 
00540         TREE_FOREACH_CHILD_REVERSE( cur, tree) {
00541                 ret = eval( cur, context );
00542                 if (ret) {
00543                         if (retval) {
00544                                 *retval = ret;
00545                         }
00546                         return cur;
00547                 }
00548         }
00549 
00550         return 0;
00551 }
00552 
00553 
00554 #define TREE_FOREACH_PREORDER(current, tree)\
00555 {\
00556         TREENODE *TREE_nextnode##next;\
00557         current = TREE_preorder_next((tree));\
00558         if (current)\
00559                 for( TREE_nextnode##next =  TREE_preorder_next(current);\
00560                             (current) && current != (tree); \
00561                                 (current) = TREE_nextnode##next, TREE_nextnode##next =  TREE_preorder_next(current)) {
00562 
00563                 
00564 #define TREE_FOREACH_PREORDER_END\
00565         }\
00566 }
00567 
00568 
00569 
00570 
00571 /*
00572  f
00573  |
00574  b-d-e
00575  | |
00576  a b-c
00577 */
00578 M_INLINE TREENODE *TREE_postorder_next(TREENODE *current, TREENODE *prev)
00579 {
00580 
00581         if (current->nextlevel_first && (!prev || current->parent == prev)) {
00582 next_level:
00583                 do {            
00584                         current = current->nextlevel_first;
00585                 }
00586                 while(current->nextlevel_first);
00587         } else {
00588                 if (current->right) {
00589                         current = current->right;
00590                         if (current->nextlevel_first) {
00591                           goto next_level;
00592                         }
00593                 } else {
00594                         if (current->parent) {
00595                                 current = current->parent;
00596                         }
00597                 }
00598         }
00599         return current;
00600 }
00601 
00602 
00603 /* wrong loop condition */
00604 #define TREE_FOREACH_POSTORDER(current, tree)\
00605 {\
00606         TREENODE *TREE_nextnode##next,*TREE_nextnode##prev;\
00607         TREE_nextnode##prev = 0; \
00608         current = TREE_postorder_next((tree),TREE_nextnode##prev);\
00609         if (current)\
00610                 for( TREE_nextnode##next =  TREE_postorder_next(current,TREE_nextnode##prev);\
00611                             (current) && current != (tree); \
00612                                 TREE_nextnode##prev = (current), \
00613                                 (current) = TREE_nextnode##next, \
00614                                 TREE_nextnode##next =  TREE_postorder_next(current,TREE_nextnode##prev)) {
00615 
00616 
00617 
00618 
00619 #define TREE_FOREACH_POSTORDER_END\
00620         }\
00621 }\
00622 
00623 /*
00624  
00625  preorder(tree)
00626  begin
00627      if tree is null, return;
00628 
00629      print(tree.root);
00630      preorder(tree.left_subtree);
00631      preorder(tree.right_subtree);
00632  end 
00633  */
00634 M_INLINE void TREE_foreach_preorder(TREENODE *node, TREE_VISITOR_V visit, void *context)
00635 {
00636         TREENODE *current;
00637 
00638         TREE_FOREACH_PREORDER(current,node)
00639                 visit(node,context);
00640         TREE_FOREACH_POSTORDER_END
00641 }
00642 
00643 M_INLINE TREENODE * TREE_find_preorder(TREENODE *node, TREE_VISITOR visit, void *context)
00644 {
00645         TREENODE *current;
00646 
00647         TREE_FOREACH_PREORDER(current,node)
00648                 if (visit(node,context)) {
00649                         return current;
00650                 }
00651         TREE_FOREACH_POSTORDER_END
00652         return 0;
00653 }
00654 
00655 
00656 
00657 /*
00658 
00659  postorder(tree)
00660  begin
00661      if tree is null, return;
00662 
00663      postorder(tree.left_subtree);
00664      postorder(tree.right_subtree);
00665      print(tree.root);
00666  end 
00667  */
00668 M_INLINE void TREE_foreach_postorder(TREENODE *node, TREE_VISITOR_V visit, void *context)
00669 {
00670         TREENODE *current;
00671 
00672         TREE_FOREACH_POSTORDER(current,node)
00673                 visit(node,context);
00674         TREE_FOREACH_POSTORDER_END
00675 }
00676 
00677 #if 0
00678 M_INLINE void TREE_foreach_preorder_ext(TREENODE *tree, TREE_VISITOR_EXT_V visit, void *context)
00679 {
00680         TREENODE *current;
00681         
00682         current = TREE_preorder_next(tree);
00683         if (current) {
00684                 for( ;
00685                          (current) && current != tree;
00686                          (current) = TREE_preorder_next_ext(current, visit, context)) {
00687                                  
00688                         visit( context, TREE_PREORDER, context );
00689                 }
00690         }
00691 
00692 }
00693 #endif
00694 
00695 M_INLINE TREENODE * TREE_find_postorder(TREENODE *node, TREE_VISITOR visit,void *context)
00696 {
00697         TREENODE *current;
00698 
00699         TREE_FOREACH_POSTORDER(current,node)
00700                 if (visit(node,context)) {
00701                         return current;
00702                 }
00703         TREE_FOREACH_POSTORDER_END
00704         return 0;
00705 }
00706 
00707 
00708 
00709 
00710 
00711 /**
00712  * @brief check tree for consistency errors
00713  * @return 0 if the tree is inconsistent
00714  */
00715 M_INLINE int TREE_check_tree(TREENODE *root)
00716 {
00717         TREENODE *firstch = root->nextlevel_first;
00718 #ifdef TREE_NEXTLEVEL_LAST
00719         TREENODE *lastch   = root->nextlevel_last;
00720 #endif
00721 #ifndef TREE_NEXTLEVEL_LEFT     
00722         TREENODE *slow,*fast, *next;
00723 #endif
00724 
00725         if (!firstch 
00726 #ifdef TREE_NEXTLEVEL_LAST
00727                         || !lastch
00728 #endif
00729                 ) {
00730 
00731 #ifdef TREE_NEXTLEVEL_LAST
00732                 if (firstch || lastch) {
00733                         return 0;
00734                 }
00735 #endif
00736                 return 1;               
00737         }       
00738         
00739         if (firstch->parent != root) {
00740                 return 0;
00741         }
00742 
00743 #ifdef TREE_NEXTLEVEL_LEFT      
00744         for(;;firstch = firstch->right) {
00745                 TREENODE *next;
00746                 
00747                 if (!firstch) {
00748                         return 0;
00749                 }
00750 
00751                 if (!TREE_check_tree(firstch)) {
00752                         return 0;
00753                 }
00754 
00755                 next = firstch->right;
00756                 if (!next) {
00757 #ifdef TREE_NEXTLEVEL_LAST
00758                         if (lastch != firstch) {
00759                                 return 0;
00760                         }
00761 #endif
00762                         break;
00763                 }
00764 
00765                 if (next->left != firstch) {
00766                         return 0;
00767                 }
00768         }
00769 #else
00770         slow=fast=firstch;
00771         while(1) {
00772                 if (!TREE_check_tree(slow)) {
00773                         return 0;
00774                 }
00775                 next = fast->right;
00776                 if (!next) {
00777                         break;                  
00778                 }
00779                 fast = next;
00780                 if (fast == slow) {
00781                         return 0;
00782                 }
00783                 next = fast->right;
00784                 if (!next) {
00785                         break;                  
00786                 }
00787                 fast = next;
00788                 if (fast == slow) {
00789                         return 0;
00790                 }
00791                 slow = slow->right;
00792         }
00793 #ifdef TREE_NEXTLEVEL_LAST
00794         if (lastch != fast) {
00795                 return 0;
00796         }
00797 #endif
00798 
00799 #endif
00800         return 1;
00801 }
00802 
00803 /**
00804  * @}
00805  */
00806 
00807 #ifdef  __cplusplus
00808 }
00809 #endif
00810 
00811 #endif