Simple data structures / objects in plain C Snapshot
|
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