tree.temp.h

Go to the documentation of this file.
00001 /* Adapted from... */
00002 /*
00003  * ANSI C Library for maintainance of AVL Balanced Trees
00004  *
00005  * ref.:
00006  *  G. M. Adelson-Velskij & E. M. Landis
00007  *  Doklady Akad. Nauk SSSR 146 (1962), 263-266
00008  *
00009  * see also:
00010  *  D. E. Knuth: The Art of Computer Programming Vol.3 (Sorting and Searching)
00011  *
00012  * (C) 2000 Daniel Nagy, Budapest University of Technology and Economics
00013  * Released under GNU General Public License (GPL) version 2
00014  * 
00015 **/
00033 #ifndef tree_temp_offset
00034 #error The 'tree_temp_offset' template parameter was not defined.  
00035 #endif
00036 
00037 #ifndef tree_temp_multiple
00038 #error The 'tree_temp_multiple' template parameter was not defined.  
00039 #endif
00040 
00041 /* Balance maintainance after especially nasty swings */
00042 #define tree_fixup(root) \
00043 {\
00044     if( (root)->balance < 0 )\
00045     {\
00046         (root)->left->balance = 0;\
00047         (root)->right->balance = 1;\
00048     }\
00049     else if( (root)->balance > 0 )\
00050     {\
00051         (root)->left->balance = -1;\
00052         (root)->right->balance = 0;\
00053     }\
00054     else\
00055     {\
00056         (root)->left->balance = 0;\
00057         (root)->right->balance = 0;\
00058     }\
00059     (root)->balance = 0;\
00060 }
00061 
00062 /* Swing to the left
00063  * Warning: no balance maintainance
00064  */
00065 #define tree_swl(root)\
00066 {\
00067     ctlt_node_type(tree_temp_offset,tree_temp_multiple) *a_swr = (root);\
00068     ctlt_node_type(tree_temp_offset,tree_temp_multiple) *b_swr = a_swr->right;\
00069     (root) = b_swr;\
00070     a_swr->right = b_swr->left;\
00071     b_swr->left = a_swr;\
00072 }
00073 
00074 /* Swing to the right
00075  * Warning: no balance maintainance
00076  */
00077 #define tree_swr(root)\
00078 {\
00079     ctlt_node_type(tree_temp_offset,tree_temp_multiple) *a_swr = (root);\
00080     ctlt_node_type(tree_temp_offset,tree_temp_multiple) *b_swr = a_swr->left;\
00081     (root) = b_swr;\
00082     a_swr->left = b_swr->right;\
00083     b_swr->right = a_swr;\
00084 }
00085 
00086 /* 
00087  * Compare two nodes, jumping through appropriate hoops
00088  * tree Tree the nodes belong to
00089  * n1 The 'lesser', or left node
00090  * n2 The 'greater', or right node
00091  * return Exactly like qsort wants
00092  */
00093 #define tree_compare( tree, n1, n2 )            (tree)->compare( ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, (tree),(n1)), ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, (tree),(n2)) )
00094 
00095 /* 
00096  * Copy one tree to another tree, setting a new root in the target tree
00097  * treedst Tree new tree
00098  * treesrc Tree original tree
00099  * dstroot New root node for tree
00100  */
00101 #define tree_copy( treedst, dstroot, treesrc )  { (treedst)->root = (dstroot); (treedst)->compare = (treesrc)->compare; ctlt_offset_for_relative(tree_temp_offset,(treedst)->data_offset = (treesrc)->data_offset;) (treedst)->size = 0; }
00102 
00103 /* 
00104  * Integrate findings from sutree treesrc into treedst tree
00105  * treedst Tree new tree
00106  * treesrc Tree original tree
00107  */
00108 #define tree_integrate( treedst, treesrc )      { (treedst)->size += (treesrc)->size; (treedst)->found = (treesrc)->found; }
00109 
00110 static bool ctl_tree_(tree_temp_offset,tree_temp_multiple, _insert )( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node );
00111 static int ctl_tree_(tree_temp_offset,tree_temp_multiple, _remove )( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node );
00112 static int ctl_tree_(tree_temp_offset,tree_temp_multiple, _removeroot )( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree );
00113 
00114 /*
00115  * Insert element a into the AVL tree t
00116  * tree The tree we are attempting to add a node to
00117  * node A fresh, new node to add to this tree
00118  * true if the depth of the tree has grown
00119  * Warning: do not insert elements already present in the tree
00120  *
00121  * tree->found is normally clear 
00122  *
00123  * If tree->tree_temp_multiple is clear, tree->found will be set if a 
00124  * node of the same value is found
00125  *
00126  * If a node is already linked to the tree, node->found will 
00127  * be that node.
00128  */
00129 static bool ctl_tree_(tree_temp_offset,tree_temp_multiple, _insert )( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node )
00130 {
00131     /* initialize */
00132     int diff;
00133     /* Inserting a node that's already linked in there is an error! */
00134     /* This assert doesn't catch every case, but it's here to catch some of them */
00135     assert( node != tree->root );
00136     tree->found = NULL;
00137     node->left = 0;
00138     node->right = 0;
00139     node->balance = 0;
00140     /* insert into an empty tree */
00141     if (!tree->root)
00142     {
00143         tree->root = node;
00144         tree->size++;
00145         return true;
00146     }
00147     diff = tree_compare( tree, tree->root, node );
00148     if( diff > 0 )
00149     {
00150         /* insert into the left sutree */
00151         if (tree->root->left)
00152         {
00153             ctl_tree(tree_temp_offset,tree_temp_multiple) left_sutree;
00154             tree_copy( &left_sutree, tree->root->left, tree );
00155             if (ctl_tree_(tree_temp_offset,tree_temp_multiple, _insert ) (&left_sutree, node))
00156             {
00157                 int tmpBalance = tree->root->balance--;
00158                 tree_integrate( tree, &left_sutree );
00159                 if( 0 == tmpBalance )
00160                     return true;
00161                 if( 1 == tmpBalance )
00162                     return false;
00163                 if (tree->root->left->balance < 0)
00164                 {
00165                     tree_swr (tree->root);
00166                     tree->root->balance = 0;
00167                     tree->root->right->balance = 0;
00168                 }
00169                 else
00170                 {
00171                     tree_swl (tree->root->left);
00172                     tree_swr (tree->root);
00173                     tree_fixup (tree->root);
00174                 }
00175             }
00176             else
00177             {
00178                 tree_integrate( tree, &left_sutree );
00179                 tree->root->left = left_sutree.root;
00180             }
00181             return false;
00182         }
00183         else
00184         {
00185             tree->root->left = node;
00186             (tree)->size++; /* Tree grew */
00187             if (tree->root->balance--)
00188                 return false;
00189             return true;
00190         }
00191     }
00192 #if ctlt_multi_value(tree_temp_multiple)
00193     else
00194 #else
00195     else if( diff < 0 ) 
00196 #endif
00197     {
00198         /* insert into the right sutree */
00199         if (tree->root->right)
00200         {
00201             ctl_tree(tree_temp_offset,tree_temp_multiple) right_sutree;
00202             tree_copy( &right_sutree, tree->root->right, tree );
00203             if (ctl_tree_(tree_temp_offset,tree_temp_multiple, _insert ) (&right_sutree, node))
00204             {
00205                 int tmpBalance = tree->root->balance++;
00206                 tree_integrate( tree, &right_sutree );
00207                 if( -1 == tmpBalance )
00208                     return false;
00209                 if( 0 == tmpBalance )
00210                     return true;
00211                 if (tree->root->right->balance > 0)
00212                 {
00213                     tree_swl (tree->root);
00214                     tree->root->balance = 0;
00215                     tree->root->left->balance = 0;
00216                 }
00217                 else
00218                 {
00219                     tree_swr (tree->root->right);
00220                     tree_swl (tree->root);
00221                     tree_fixup (tree->root);
00222                 }
00223             }
00224             else
00225             {
00226                 tree_integrate( tree, &right_sutree );
00227                 tree->root->right = right_sutree.root;
00228             }
00229             return false;
00230         }
00231         else
00232         {
00233             tree->root->right = node;
00234             (tree)->size++; /* Tree grew */
00235             if (tree->root->balance++)
00236                 return false;
00237             return true;
00238         }
00239     }
00240 #if ctlt_multi_not_value(tree_temp_multiple)
00241     /* else that value is already in there */
00242     tree->found = tree->root;
00243     return false;
00244 #endif
00245 }
00246 
00247 
00248 /*
00249  * Remove the root of the AVL tree 
00250  * tree The tree we're popping the top off
00251  *
00252  * This is where the actual work of removing the node happens, when 
00253  * it's been found while recursing into the tree.
00254  * 
00255  * Warning: dumps core if tree is empty
00256  */
00257 static int ctl_tree_(tree_temp_offset,tree_temp_multiple, _removeroot )( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree )
00258 {
00259     int ch;
00260     ctlt_node_type(tree_temp_offset,tree_temp_multiple) *node;
00261     ctlt_node_type(tree_temp_offset,tree_temp_multiple) *root = tree->root;
00262     /* Warning: dumps core if tree is empty */
00263     assert(root);
00264     /* See if we can trivially remove the root node - if left or right are clear, we can patch this up easy. */
00265     if (!root->left)
00266     {
00267         (tree)->found = root;
00268         (tree)->size--; /* Tree shrinks */
00269         if (!root->right)
00270         {
00271             tree->root = 0;
00272             return -1;
00273         }
00274         tree->root = root->right;
00275         return -1;
00276     }
00277     if (!root->right)
00278     {
00279         (tree)->found = root;
00280         tree->root = root->left;
00281         (tree)->size--;     /* Tree shrinks */
00282         return -1;
00283     }
00284     /* Recurse down and see if we can rotate/pop something to make one side of root clear */
00285     if (root->balance < 0)
00286     {
00287         /* remove from the left sutree */
00288         node = root->left;
00289         while (node->right)
00290             node = node->right;
00291     }
00292     else
00293     {
00294         /* remove from the right sutree */
00295         node = root->right;
00296         while (node->left)
00297             node = node->left;
00298     }
00299     /* This decrements count for us */
00300     ch = ctl_tree_(tree_temp_offset,tree_temp_multiple, _remove ) (tree, node);
00301     root = tree->root;
00302     node->left = root->left;
00303     node->right = root->right;
00304     node->balance = root->balance;
00305     tree->root = node;
00306     if (node->balance == 0)
00307         return ch;
00308     return 0;
00309 }
00310 
00311 /*
00312  * Remove an explicit node element from the AVL tree 
00313  * tree Tree to insert element into
00314  * node node to remove
00315  * return -1 if the depth of the tree has shrunk
00316  * Warning: if the element is not present in the tree, returns 0 as if it had been removed succesfully.
00317  */
00318 static int ctl_tree_(tree_temp_offset,tree_temp_multiple, _remove )( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node )
00319 {
00320     /* Recursively search tree passing left or right sutrees to self */
00321     /* Call ctl_tree_(tree_temp_offset,tree_temp_multiple, _removeroot ) when we have a candidate */
00322     int b;
00323     if (tree->root == node)
00324         return ctl_tree_(tree_temp_offset,tree_temp_multiple, _removeroot ) (tree);
00325     b = tree_compare( tree, tree->root, node );
00326     if (b >= 0)
00327     {
00328         /* remove from the left sutree */
00329         int ch;
00330         ctl_tree(tree_temp_offset,tree_temp_multiple) left_sutree;
00331         tree_copy( &left_sutree, tree->root->left, tree );
00332         if (left_sutree.root )
00333         {
00334             ch = ctl_tree_(tree_temp_offset,tree_temp_multiple, _remove ) (&left_sutree, node);
00335             tree_integrate( tree, &left_sutree );
00336             tree->root->left = left_sutree.root;
00337             if (ch)
00338             {
00339                 int tmpBalance = tree->root->balance++;
00340                 if( -1 == tmpBalance)
00341                     return -1;
00342                 if( 0 == tmpBalance)
00343                     return 0;
00344                 tmpBalance = tree->root->right->balance;
00345                 if( 0 == tmpBalance )
00346                 {
00347                     tree_swl (tree->root);
00348                     tree->root->balance = -1;
00349                     tree->root->left->balance = 1;
00350                     return 0;
00351                 }
00352                 if( 1 == tmpBalance )
00353                 {
00354                     tree_swl (tree->root);
00355                     tree->root->balance = 0;
00356                     tree->root->left->balance = 0;
00357                     return -1;
00358                 }
00359                 tree_swr (tree->root->right);
00360                 tree_swl (tree->root);
00361                 tree_fixup (tree->root);
00362                 return -1;
00363             }
00364         }
00365     }
00366     if (b <= 0)
00367     {
00368         /* remove from the right sutree */
00369         int ch;
00370         ctl_tree(tree_temp_offset,tree_temp_multiple) right_sutree;
00371         tree_copy( &right_sutree, tree->root->right, tree );
00372         if (right_sutree.root )
00373         {
00374             ch = ctl_tree_(tree_temp_offset,tree_temp_multiple, _remove ) (&right_sutree, node);
00375             tree_integrate( tree, &right_sutree );
00376             tree->root->right = right_sutree.root;
00377             if (ch)
00378             {
00379                 int tmpBalance = tree->root->balance--;
00380                 if( 1 == tmpBalance )
00381                     return -1;
00382                 if( 0 == tmpBalance )
00383                     return 0;
00384 
00385                 tmpBalance = tree->root->left->balance;
00386                 if( 0 == tmpBalance )
00387                 {
00388                     tree_swr (tree->root);
00389                     tree->root->balance = 1;
00390                     tree->root->right->balance = -1;
00391                     return 0;
00392                 }
00393                 if( -1 == tmpBalance )
00394                 {
00395                     tree_swr (tree->root);
00396                     tree->root->balance = 0;
00397                     tree->root->right->balance = 0;
00398                     return -1;
00399                 }
00400                 tree_swl (tree->root->left);
00401                 tree_swr (tree->root);
00402                 tree_fixup (tree->root);
00403                 return -1;
00404             }
00405         }
00406     }
00407     return 0;
00408 }
00409 
00418 ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, insert)( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, ctlt_offset_type(tree_temp_offset)* data )
00419 {
00420     ppDebug(size_t size = tree->size;)
00421     ctlt_node_type(tree_temp_offset,tree_temp_multiple) *node = ctl_tree_data_to_node(tree_temp_offset,tree_temp_multiple, tree,data);
00422     ctl_tree_(tree_temp_offset,tree_temp_multiple, _insert )(tree, node);
00423     if( !tree->found )
00424     {
00425         assert( size < tree->size );
00426         return data;
00427     }
00428     return ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,tree->found);
00429 }
00430 
00439 ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, remove)( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, ctlt_offset_type(tree_temp_offset)* data )
00440 {
00441     data = (ctlt_offset_type(tree_temp_offset)*)ctl_tree_(tree_temp_offset,tree_temp_multiple, find)( tree, data );
00442     if( data )
00443     {
00444         ppDebug(size_t size = tree->size;)
00445         ctlt_node_type(tree_temp_offset,tree_temp_multiple) *node = ctl_tree_data_to_node(tree_temp_offset,tree_temp_multiple, tree,data);
00446         ctl_tree_(tree_temp_offset,tree_temp_multiple, _remove )( tree, node );
00447         assert( size > tree->size );
00448         return ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,node);
00449     }
00450     return NULL;
00451 }
00452 
00461 ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, unlink)( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, ctlt_offset_type(tree_temp_offset)* data )
00462 {
00463     assertobjptr( tree );
00464     assertptr( data, sizeof(void*) );
00465     {
00466         ppDebug(size_t size = tree->size;)
00467         ctlt_node_type(tree_temp_offset,tree_temp_multiple) *node = ctl_tree_data_to_node(tree_temp_offset,tree_temp_multiple, tree,data);
00468         ctl_tree_(tree_temp_offset,tree_temp_multiple, _remove )( tree, node );
00469         assert( size > tree->size );
00470         return ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,node);
00471     }
00472 }
00473 
00479 void ctl_tree_(tree_temp_offset,tree_temp_multiple, recurseunlink)( ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node )
00480 {
00481     if( node->left )
00482         ctl_tree_(tree_temp_offset,tree_temp_multiple, recurseunlink)( node->left );
00483     if( node->right )
00484         ctl_tree_(tree_temp_offset,tree_temp_multiple, recurseunlink)( node->right );
00485     node->left = node->right = NULL;
00486 }
00487 
00493 void ctl_tree_(tree_temp_offset,tree_temp_multiple, reset)( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree )
00494 {
00495     if( tree->root )
00496         ctl_tree_(tree_temp_offset,tree_temp_multiple, recurseunlink)( tree->root );
00497     tree->root = NULL;
00498     tree->size = 0;
00499 }
00500 
00507 static size_t ctl_tree_(tree_temp_offset,tree_temp_multiple, recursetally)( ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node )
00508 {
00509     if( node )
00510         return 1 + ctl_tree_(tree_temp_offset,tree_temp_multiple, recursetally( node->left )) + ctl_tree_(tree_temp_offset,tree_temp_multiple, recursetally)( node->right );
00511     return 0;
00512 }
00513 
00520 size_t ctl_tree_(tree_temp_offset,tree_temp_multiple, tally)( const ctl_tree(tree_temp_offset,tree_temp_multiple)* tree )
00521 {
00522     /* This DID iterate the nodes from begin->end, but that actually  */
00523     /* visited nodes many times.  See ctl_tree_next for what  */
00524     /* would've been needed.  The tree keeps a count, but this  */
00525     /* is mainly to verify that this cound is correct. */
00526     size_t size = ctl_tree_(tree_temp_offset,tree_temp_multiple, recursetally)( tree->root );
00527     assert( size == tree->size );
00528     return size;
00529 }
00530 
00538 static size_t ctl_tree_(tree_temp_offset,tree_temp_multiple, recursedepth)( const ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node, size_t currDepth )
00539 {
00540     if( node )
00541     {
00542         size_t d1 = ctl_tree_(tree_temp_offset,tree_temp_multiple, recursedepth)( node->left, currDepth+1 );
00543         size_t d2 = ctl_tree_(tree_temp_offset,tree_temp_multiple, recursedepth)( node->right, currDepth+1 );
00544         return max(d1,d2);
00545     }
00546     return currDepth;
00547 }
00548 
00559 size_t ctl_tree_(tree_temp_offset,tree_temp_multiple, depth)( const ctl_tree(tree_temp_offset,tree_temp_multiple)* tree )
00560 {
00561     return ctl_tree_(tree_temp_offset,tree_temp_multiple, recursedepth)( tree->root, 1 );
00562 }
00563 
00570 const ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, front)( const ctl_tree(tree_temp_offset,tree_temp_multiple)* tree )
00571 {
00572     const ctlt_node_type(tree_temp_offset,tree_temp_multiple) *node = tree->root;
00573     if( !node )
00574         return NULL;
00575     while( node->left )
00576         node = node->left;
00577     return ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,node);
00578 }
00579 
00586 const ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, back)( const ctl_tree(tree_temp_offset,tree_temp_multiple)* tree )
00587 {
00588     const ctlt_node_type(tree_temp_offset,tree_temp_multiple) *node = tree->root;
00589     if( !node )
00590         return NULL;
00591     while( node->left )
00592         node = node->left;
00593     return ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,node);
00594 }
00595 
00603 const ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, find)( const ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, const ctlt_offset_type(tree_temp_offset)* data )
00604 {
00605     tree_compare compare = tree->compare;
00606     const ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node = tree->root;
00607     while( node )
00608     {
00609         int diff = compare( data, ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,node) );
00610         if( diff > 0 )
00611             node = node->right;
00612         else if( diff < 0 )
00613             node = node->left;
00614         else
00615             return ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,node);
00616     }
00617     return NULL;
00618 }
00619 
00626 ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, pop_front)( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree )
00627 {
00628     ctlt_node_type(tree_temp_offset,tree_temp_multiple) *node = tree->root;
00629     if( !node )
00630         return NULL;
00631     while( node->left )
00632         node = node->left;
00633     ctl_tree_(tree_temp_offset,tree_temp_multiple, _remove )( tree, node );
00634     return ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,node);
00635 }
00636 
00643 ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, pop_back)( ctl_tree(tree_temp_offset,tree_temp_multiple)* tree )
00644 {
00645     ctlt_node_type(tree_temp_offset,tree_temp_multiple) *node = tree->root;
00646     if( !node )
00647         return NULL;
00648     while( node->right )
00649         node = node->right;
00650     ctl_tree_(tree_temp_offset,tree_temp_multiple, _remove )( tree, node );
00651     return ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,node);
00652 }
00653 
00661 const ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_begin)( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator )* stack, const ctl_tree(tree_temp_offset,tree_temp_multiple)* tree )
00662 {
00663     const ctlt_node_type(tree_temp_offset,tree_temp_multiple) *node = tree->root;
00664     stack->tree = tree;
00665     stack->sp = stack->stack;
00666     *stack->sp++ = NULL;    /* When we pop NULL off, we're done. */
00667     while( node )
00668     {
00669         *stack->sp++ = node;
00670         node = node->left;
00671     }
00672     /* Heap/stack/BSS/whatever is probably already corrupted if this assert hits */
00673     assert( memberof(stack->stack,stack->sp) );
00674     return ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_next)( stack );
00675 }
00676 
00685 static bool ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_begin_from_no_iterate)( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator )* stack, const ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, const ctlt_offset_type(tree_temp_offset)* data )
00686 {
00687     tree_compare compare = tree->compare;
00688     const ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node = tree->root;
00689     stack->tree = tree;
00690     stack->sp = stack->stack;
00691     *stack->sp++ = NULL;    /* When we pop NULL off, we're done. */
00692     while( node )
00693     {
00694         int diff = compare( data, ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,node) );
00695         if( diff > 0 )
00696         {
00697             node = node->right;
00698         }
00699         else 
00700 #if ctlt_multi_not_value(tree_temp_multiple)
00701         if( diff < 0 )  /* If we allow tree_temp_multiple of the same value, we must carry on iterating leftward until we hit NULL */
00702 #endif
00703         {
00704             *stack->sp++ = node;
00705             node = node->left;
00706         }
00707 #if ctlt_multi_not_value(tree_temp_multiple)
00708         else
00709         {
00710             /* We found the unique value we were looking for */
00711             *stack->sp++ = node;
00712             /* Heap/stack/BSS/whatever is probably already corrupted if this assert hits */
00713             assert( memberof(stack->stack,stack->sp) );
00714             return true;
00715         }
00716 #endif
00717     }
00718     /* Heap/stack/BSS/whatever is probably already corrupted if this assert hits */
00719     assert( memberof(stack->stack,stack->sp) );
00720     return false;
00721 }
00722 
00731 const ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_begin_from)( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator )* stack, const ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, const ctlt_offset_type(tree_temp_offset)* data )
00732 {
00733     /* Heap/stack/BSS/whatever is probably already corrupted if this assert hits */
00734     if( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_begin_from_no_iterate)( stack, tree, data ) )
00735         return ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_next)( stack );
00736     /* If value wasn't found, or wasn't unique we probably iterated past a starting value we wanted. */
00737     /* Seek right until we are at first instance */
00738     {
00739         tree_compare compare = tree->compare;
00740         const ctlt_offset_type(tree_temp_offset)* curr = ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_next)( stack );
00741         while( curr && compare( data, curr ) > 0 )
00742             curr = ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_next)( stack );
00743         return curr;
00744     }
00745 }
00746 
00754 const ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_next)( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator )* stack )
00755 {
00756     /* Pop node */
00757     const ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node = *--stack->sp;
00758     if( node )
00759     {
00760         if( node->right )
00761         {
00762             /* Add search path to go left from right node */
00763             const ctlt_node_type(tree_temp_offset,tree_temp_multiple)* next = node->right;
00764             while( next )
00765             {
00766                 *stack->sp++ = next;
00767                 next = next->left;
00768             }
00769         }
00770         stack->node = node;
00771         return ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, stack->tree,node);
00772     }
00773     stack->node = NULL;
00774     return NULL;
00775 }
00776 
00784 const ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_rbegin)( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator )* stack, const ctl_tree(tree_temp_offset,tree_temp_multiple) *tree )
00785 {
00786     const ctlt_node_type(tree_temp_offset,tree_temp_multiple) *node = tree->root;
00787     stack->tree = tree;
00788     stack->bReverse = true;
00789     stack->sp = stack->stack;
00790     *stack->sp++ = NULL;    /* When we pop NULL off, we're done. */
00791     while( node )
00792     {
00793         *stack->sp++ = node;
00794         node = node->right;
00795     }
00796     /* Heap/stack/BSS/whatever is probably already corrupted if this assert hits */
00797     assert( memberof(stack->stack,stack->sp) );
00798     return ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_prev)( stack );
00799 }
00800 
00809 static bool ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_rbegin_from_no_iterate)( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator )* stack, const ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, const ctlt_offset_type(tree_temp_offset)* data )
00810 {
00811     tree_compare compare = tree->compare;
00812     const ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node = tree->root;
00813     stack->tree = tree;
00814     stack->bReverse = true;
00815     stack->sp = stack->stack;
00816     *stack->sp++ = NULL;    /* When we pop NULL off, we're done. */
00817     while( node )
00818     {
00819         int diff = compare( data, ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,node) );
00820         if( diff < 0 )
00821         {
00822             node = node->left;
00823         }
00824         else 
00825 #if ctlt_multi_not_value(tree_temp_multiple)
00826             if( diff > 0 )  /* If we allow tree_temp_multiple of the same value, we must carry on iterating leftward until we hit NULL */
00827 #endif
00828         {
00829             *stack->sp++ = node;
00830             node = node->right;
00831         }
00832 #if ctlt_multi_not_value(tree_temp_multiple)
00833         else
00834         {
00835             /* We found the unique value we were looking for */
00836             *stack->sp++ = node;
00837             /* Heap/stack/BSS/whatever is probably already corrupted if this assert hits */
00838             assert( memberof(stack->stack,stack->sp) );
00839             return true;
00840         }
00841 #endif
00842     }
00843     /* Heap/stack/BSS/whatever is probably already corrupted if this assert hits */
00844     assert( memberof(stack->stack,stack->sp) );
00845     return false;
00846 }
00847 
00856 const ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_rbegin_from)( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator )* stack, const ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, const ctlt_offset_type(tree_temp_offset)* data )
00857 {
00858     if( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_rbegin_from_no_iterate)( stack, tree, data ) )
00859         return ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_prev)( stack );
00860     /* If value wasn't found, or wasn't unique we probably iterated past a starting value we wanted. */
00861     {
00862         tree_compare compare = tree->compare;
00863         const ctlt_offset_type(tree_temp_offset)* curr = ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_prev)( stack );
00864         while( curr && compare( data, curr ) < 0 )
00865             curr = ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_prev)( stack );
00866         return curr;
00867     }
00868 }
00869 
00876 const ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_prev)( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator )* stack )
00877 {
00878     /* Pop node */
00879     const ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node = *--stack->sp;
00880     if( node )
00881     {
00882         if( node->left )
00883         {
00884             /* Add search path to go right from left node */
00885             const ctlt_node_type(tree_temp_offset,tree_temp_multiple)* prev = node->left;
00886             while( prev )
00887             {
00888                 *stack->sp++ = prev;
00889                 prev = prev->right;
00890             }
00891         }
00892         stack->node = node;
00893         return ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, stack->tree,node);
00894     }
00895     stack->node = NULL;
00896     return NULL;
00897 }
00898 
00906 const ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, unlink_curr)( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator )* stack )
00907 {
00908     if( stack->node )
00909     {
00910         ctl_tree_(tree_temp_offset,tree_temp_multiple, _remove )( (ctl_tree(tree_temp_offset,tree_temp_multiple)*)stack->tree, (ctlt_node_type(tree_temp_offset,tree_temp_multiple)*)stack->node );
00911         return ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, stack->tree,stack->node);
00912     }
00913     return NULL;
00914 }
00915 
00923 const ctlt_offset_type(tree_temp_offset)* ctl_tree_(tree_temp_offset,tree_temp_multiple, unlink_curr_resume)( ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator )* stack )
00924 {
00925     if( stack->node )
00926     {
00927         ctl_tree_(tree_temp_offset,tree_temp_multiple, _remove )( (ctl_tree(tree_temp_offset,tree_temp_multiple)*)stack->tree, (ctlt_node_type(tree_temp_offset,tree_temp_multiple)*)stack->node );
00928         if( stack->bReverse )
00929             return ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_rbegin_from)( stack, stack->tree, ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, stack->tree,stack->node) );
00930         else
00931             return ctl_tree_(tree_temp_offset,tree_temp_multiple, iterator_begin_from)( stack, stack->tree, ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, stack->tree,stack->node) );
00932     }
00933     return NULL;
00934 }
00935 
00936 #ifdef CTL_UNIT
00937 #define CelWidth    2
00938 static void ctl_tree_(tree_temp_offset,tree_temp_multiple, cell_printLines)( ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node, char **buff, size_t coloffset, size_t width )
00939 {
00940     size_t line;
00941     size_t c = coloffset + width;
00942     size_t nLines = (width / 2);
00943     for (line = 1; line <= nLines; ++line)
00944     {
00945 /*      if( node->left ) */
00946         buff[line][1 + c - line] = '/';
00947 /*      if( node->right ) */
00948         buff[line][c + line] = '\\';
00949     }
00950 }
00951 
00965 static void ctl_tree_(tree_temp_offset,tree_temp_multiple, cell_print)( const ctl_tree(tree_temp_offset,tree_temp_multiple)* tree, ctlt_node_type(tree_temp_offset,tree_temp_multiple)* node, char **buff, size_t coloffset, size_t width, size_t depth, ctl_tree_printf print, ctlt_node_type(tree_temp_offset,tree_temp_multiple)* nHilight)
00966 {
00967     size_t center = coloffset + (width / 2);
00968     char *pBuff = *buff + center;
00969     if (NULL == node)
00970     {
00971         memcpy (pBuff, "{}", 2);
00972     }
00973     else
00974     {
00975         char tmp[80];
00976         size_t len = print( ctl_tree_node_to_data(tree_temp_offset,tree_temp_multiple, tree,node), tmp, countof (tmp));
00977         len = min (len, width);
00978         pBuff -= -1 + (len / 2) + (nHilight == node) + (0 != node->balance);
00979         if( nHilight == node )
00980             *pBuff++ = '[';
00981         memcpy (pBuff, tmp, len);
00982         pBuff += len;
00983         if( node->balance < 0 )
00984             *pBuff++ = '-';
00985         else if( node->balance > 0 )
00986             *pBuff++ = '+';
00987         if( nHilight == node )
00988             *pBuff++ = ']';
00989 
00990         ctl_tree_(tree_temp_offset,tree_temp_multiple, cell_printLines)(node, buff, coloffset, width / 2);
00991         ctl_tree_(tree_temp_offset,tree_temp_multiple, cell_print)(tree, node->left, buff + 1 + width / 4, coloffset, width / 2, depth + 1, print, nHilight);
00992         ctl_tree_(tree_temp_offset,tree_temp_multiple, cell_print)(tree, node->right, buff + 1 + width / 4, center, width / 2, depth + 1, print, nHilight);
00993     }
00994 }
00995 
01004 void ctl_tree_(tree_temp_offset,tree_temp_multiple, pretty_print)( const ctl_tree(tree_temp_offset,tree_temp_multiple) *tree, ctl_tree_printf print, ctlt_node_type(tree_temp_offset,tree_temp_multiple)* hilight )
01005 {
01006     size_t maxDepth = ctl_tree_(tree_temp_offset,tree_temp_multiple, depth)(tree);
01007     size_t bottomWidth = 1 << maxDepth;
01008     size_t lineCount = bottomWidth+maxDepth;
01009     char **cells = malloc (lineCount * sizeof (char *));
01010     size_t rowWidth = CelWidth * bottomWidth;
01011     size_t rowCurr;
01012 
01013     /* Allocate a buffer to draw into */
01014     for (rowCurr = 0; rowCurr < lineCount; ++rowCurr)
01015     {
01016         cells[rowCurr] = malloc (rowWidth + CelWidth + 1);
01017         memset (cells[rowCurr], ' ', rowWidth + CelWidth + 1);
01018         cells[rowCurr][rowWidth + CelWidth] = 0;
01019     }
01020     ctl_tree_(tree_temp_offset,tree_temp_multiple, cell_print)( tree, tree->root, cells, 0, rowWidth, 0, print, hilight );
01021     for (rowCurr = 0; rowCurr < lineCount; ++rowCurr)
01022     {
01023         puts (cells[rowCurr]);
01024         free (cells[rowCurr]);
01025     }
01026     free (cells);
01027     puts ("\n");
01028 }
01029 #endif /* CTL_UNIT */
01030 
01031 /* Undefine local definitions */
01032 #undef tree_fixup
01033 #undef tree_swl
01034 #undef tree_swr
01035 #undef tree_compare
01036 #undef tree_copy
01037 #undef tree_integrate

Generated on Fri Jan 2 15:28:35 2009 for Squat by  doxygen 1.5.6