Shadowrun: Awakened 29 September 2011 - Build 871
DS_BinarySearchTree.h
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #ifndef __BINARY_SEARCH_TREE_H
00011 #define __BINARY_SEARCH_TREE_H
00012 
00013 #include "DS_QueueLinkedList.h"
00014 #include "RakMemoryOverride.h"
00015 #include "Export.h"
00016 
00017 
00018 #ifdef _MSC_VER
00019 #pragma warning( push )
00020 #endif
00021 
00024 namespace DataStructures
00025 {
00088     template <class BinarySearchTreeType>
00089     class RAK_DLL_EXPORT BinarySearchTree
00090     {
00091     
00092     public:
00093 
00094         struct node
00095         {
00096             BinarySearchTreeType* item;
00097             node* left;
00098             node* right;
00099         };
00100         
00101         BinarySearchTree();
00102         virtual ~BinarySearchTree();
00103         BinarySearchTree( const BinarySearchTree& original_type );
00104         BinarySearchTree& operator= ( const BinarySearchTree& original_copy );
00105         unsigned int Size( void );
00106         void Clear( const char *file, unsigned int line );
00107         unsigned int Height( node* starting_node = 0 );
00108         node* Add ( const BinarySearchTreeType& input, const char *file, unsigned int line );
00109         node* Del( const BinarySearchTreeType& input, const char *file, unsigned int line );
00110         bool IsIn( const BinarySearchTreeType& input );
00111         void DisplayInorder( BinarySearchTreeType* return_array );
00112         void DisplayPreorder( BinarySearchTreeType* return_array );
00113         void DisplayPostorder( BinarySearchTreeType* return_array );
00114         void DisplayBreadthFirstSearch( BinarySearchTreeType* return_array );
00115         BinarySearchTreeType*& GetPointerToNode( const BinarySearchTreeType& element );
00116         
00117     protected:
00118 
00119         node* root;
00120         
00121         enum Direction_Types
00122         {
00123             NOT_FOUND, LEFT, RIGHT, ROOT
00124         } direction;
00125         unsigned int HeightRecursive( node* current );
00126         unsigned int BinarySearchTree_size;
00127         node*& Find( const BinarySearchTreeType& element, node** parent );
00128         node*& FindParent( const BinarySearchTreeType& element );
00129         void DisplayPostorderRecursive( node* current, BinarySearchTreeType* return_array, unsigned int& index );
00130         void FixTree( node* current );
00131         
00132     };
00133     
00135     template <class BinarySearchTreeType>
00136     class RAK_DLL_EXPORT AVLBalancedBinarySearchTree : public BinarySearchTree<BinarySearchTreeType>
00137     {
00138     
00139     public:
00140         AVLBalancedBinarySearchTree()   {}
00141         virtual ~AVLBalancedBinarySearchTree();
00142         void Add ( const BinarySearchTreeType& input );
00143         void Del( const BinarySearchTreeType& input );
00144         BinarySearchTree<BinarySearchTreeType>& operator= ( BinarySearchTree<BinarySearchTreeType>& original_copy )
00145         {
00146             return BinarySearchTree<BinarySearchTreeType>::operator= ( original_copy );
00147         }
00148         
00149     private:
00150         void BalanceTree( typename BinarySearchTree<BinarySearchTreeType>::node* current, bool rotateOnce );
00151         void RotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *C );
00152         void RotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node* C );
00153         void DoubleRotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *A );
00154         void DoubleRotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node* A );
00155         bool RightHigher( typename BinarySearchTree<BinarySearchTreeType>::node* A );
00156         bool LeftHigher( typename BinarySearchTree<BinarySearchTreeType>::node* A );
00157     };
00158     
00159     template <class BinarySearchTreeType>
00160     void AVLBalancedBinarySearchTree<BinarySearchTreeType>::BalanceTree( typename BinarySearchTree<BinarySearchTreeType>::node* current, bool rotateOnce )
00161     {
00162         int left_height, right_height;
00163         
00164         while ( current )
00165         {
00166             if ( current->left == 0 )
00167                 left_height = 0;
00168             else
00169                 left_height = Height( current->left );
00170                 
00171             if ( current->right == 0 )
00172                 right_height = 0;
00173             else
00174                 right_height = Height( current->right );
00175                 
00176             if ( right_height - left_height == 2 )
00177             {
00178                 if ( RightHigher( current->right ) )
00179                     RotateLeft( current->right );
00180                 else
00181                     DoubleRotateLeft( current );
00182                     
00183                 if ( rotateOnce )
00184                     break;
00185             }
00186             
00187             else
00188                 if ( right_height - left_height == -2 )
00189                 {
00190                     if ( LeftHigher( current->left ) )
00191                         RotateRight( current->left );
00192                     else
00193                         DoubleRotateRight( current );
00194                         
00195                     if ( rotateOnce )
00196                         break;
00197                 }
00198                 
00199             if ( current == this->root )
00200                 break;
00201                 
00202             current = FindParent( *( current->item ) );
00203             
00204         }
00205     }
00206     
00207     template <class BinarySearchTreeType>
00208     void AVLBalancedBinarySearchTree<BinarySearchTreeType>::Add ( const BinarySearchTreeType& input )
00209     {
00210     
00211         typename BinarySearchTree<BinarySearchTreeType>::node * current = BinarySearchTree<BinarySearchTreeType>::Add ( input, _FILE_AND_LINE_ );
00212         BalanceTree( current, true );
00213     }
00214     
00215     template <class BinarySearchTreeType>
00216     void AVLBalancedBinarySearchTree<BinarySearchTreeType>::Del( const BinarySearchTreeType& input )
00217     {
00218         typename BinarySearchTree<BinarySearchTreeType>::node * current = BinarySearchTree<BinarySearchTreeType>::Del( input, _FILE_AND_LINE_ );
00219         BalanceTree( current, false );
00220         
00221     }
00222     
00223     template <class BinarySearchTreeType>
00224     bool AVLBalancedBinarySearchTree<BinarySearchTreeType>::RightHigher( typename BinarySearchTree<BinarySearchTreeType>::node *A )
00225     {
00226         if ( A == 0 )
00227             return false;
00228             
00229         return Height( A->right ) > Height( A->left );
00230     }
00231     
00232     template <class BinarySearchTreeType>
00233     bool AVLBalancedBinarySearchTree<BinarySearchTreeType>::LeftHigher( typename BinarySearchTree<BinarySearchTreeType>::node *A )
00234     {
00235         if ( A == 0 )
00236             return false;
00237             
00238         return Height( A->left ) > Height( A->right );
00239     }
00240     
00241     template <class BinarySearchTreeType>
00242     void AVLBalancedBinarySearchTree<BinarySearchTreeType>::RotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *C )
00243     {
00244         typename BinarySearchTree<BinarySearchTreeType>::node * A, *B, *D;
00245         /*
00246           RIGHT ROTATION
00247         
00248           A = parent(b)
00249           b= parent(c)
00250           c  = node to rotate around
00251         
00252           A
00253           | // Either direction
00254           B
00255           /   \
00256           C
00257           /   \
00258           D
00259         
00260           TO
00261         
00262           A
00263           | // Either Direction
00264           C
00265           /   \
00266           B
00267           /   \
00268           D
00269         
00270         
00271           <Leave all other branches branches AS-IS whether they point to another node or simply 0>
00272         
00273         */
00274         
00275         B = FindParent( *( C->item ) );
00276         A = FindParent( *( B->item ) );
00277         D = C->right;
00278         
00279         if ( A )
00280         {
00281             // Direction was set by the last find_parent call
00282             
00283             if ( this->direction == this->LEFT )
00284                 A->left = C;
00285             else
00286                 A->right = C;
00287         }
00288         
00289         else
00290             this->root = C;  // If B has no parent parent then B must have been the root node
00291             
00292         B->left = D;
00293         
00294         C->right = B;
00295     }
00296     
00297     template <class BinarySearchTreeType>
00298     void AVLBalancedBinarySearchTree<BinarySearchTreeType>::DoubleRotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *A )
00299     {
00300         // The left side of the left child must be higher for the tree to balance with a right rotation.  If it isn't, rotate it left before the normal rotation so it is.
00301         RotateLeft( A->left->right );
00302         RotateRight( A->left );
00303     }
00304     
00305     template <class BinarySearchTreeType>
00306     void AVLBalancedBinarySearchTree<BinarySearchTreeType>::RotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node *C )
00307     {
00308         typename BinarySearchTree<BinarySearchTreeType>::node * A, *B, *D;
00309         /*
00310           RIGHT ROTATION
00311         
00312           A = parent(b)
00313           b= parent(c)
00314           c  = node to rotate around
00315         
00316           A
00317           | // Either direction
00318           B
00319           /   \
00320           C
00321           /  \
00322           D
00323         
00324           TO
00325         
00326           A
00327           | // Either Direction
00328           C
00329           /   \
00330           B
00331           /   \
00332           D
00333         
00334         
00335           <Leave all other branches branches AS-IS whether they point to another node or simply 0>
00336         
00337         */
00338         
00339         B = FindParent( *( C->item ) );
00340         A = FindParent( *( B->item ) );
00341         D = C->left;
00342         
00343         if ( A )
00344         {
00345             // Direction was set by the last find_parent call
00346             
00347             if ( this->direction == this->LEFT )
00348                 A->left = C;
00349             else
00350                 A->right = C;
00351         }
00352         
00353         else
00354             this->root = C;  // If B has no parent parent then B must have been the root node
00355             
00356         B->right = D;
00357         
00358         C->left = B;
00359     }
00360     
00361     template <class BinarySearchTreeType>
00362     void AVLBalancedBinarySearchTree<BinarySearchTreeType>::DoubleRotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node *A )
00363     {
00364         // The left side of the right child must be higher for the tree to balance with a left rotation.  If it isn't, rotate it right before the normal rotation so it is.
00365         RotateRight( A->right->left );
00366         RotateLeft( A->right );
00367     }
00368     
00369     template <class BinarySearchTreeType>
00370     AVLBalancedBinarySearchTree<BinarySearchTreeType>::~AVLBalancedBinarySearchTree()
00371     {
00372         this->Clear(_FILE_AND_LINE_);
00373     }
00374     
00375     template <class BinarySearchTreeType>
00376     unsigned int BinarySearchTree<BinarySearchTreeType>::Size( void )
00377     {
00378         return BinarySearchTree_size;
00379     }
00380     
00381     template <class BinarySearchTreeType>
00382     unsigned int BinarySearchTree<BinarySearchTreeType>::Height( typename BinarySearchTree::node* starting_node )
00383     {
00384         if ( BinarySearchTree_size == 0 || starting_node == 0 )
00385             return 0;
00386         else
00387             return HeightRecursive( starting_node );
00388     }
00389     
00390     // Recursively return the height of a binary tree
00391     template <class BinarySearchTreeType>
00392     unsigned int BinarySearchTree<BinarySearchTreeType>::HeightRecursive( typename BinarySearchTree::node* current )
00393     {
00394         unsigned int left_height = 0, right_height = 0;
00395         
00396         if ( ( current->left == 0 ) && ( current->right == 0 ) )
00397             return 1; // Leaf
00398             
00399         if ( current->left != 0 )
00400             left_height = 1 + HeightRecursive( current->left );
00401             
00402         if ( current->right != 0 )
00403             right_height = 1 + HeightRecursive( current->right );
00404             
00405         if ( left_height > right_height )
00406             return left_height;
00407         else
00408             return right_height;
00409     }
00410     
00411     template <class BinarySearchTreeType>
00412     BinarySearchTree<BinarySearchTreeType>::BinarySearchTree()
00413     {
00414         BinarySearchTree_size = 0;
00415         root = 0;
00416     }
00417     
00418     template <class BinarySearchTreeType>
00419     BinarySearchTree<BinarySearchTreeType>::~BinarySearchTree()
00420     {
00421         this->Clear(_FILE_AND_LINE_);
00422     }
00423     
00424     template <class BinarySearchTreeType>
00425     BinarySearchTreeType*& BinarySearchTree<BinarySearchTreeType>::GetPointerToNode( const BinarySearchTreeType& element )
00426     {
00427         static typename BinarySearchTree::node * tempnode;
00428         static BinarySearchTreeType* dummyptr = 0;
00429         tempnode = Find ( element, &tempnode );
00430         
00431         if ( this->direction == this->NOT_FOUND )
00432             return dummyptr;
00433             
00434         return tempnode->item;
00435     }
00436     
00437     template <class BinarySearchTreeType>
00438     typename BinarySearchTree<BinarySearchTreeType>::node*& BinarySearchTree<BinarySearchTreeType>::Find( const BinarySearchTreeType& element, typename BinarySearchTree<BinarySearchTreeType>::node** parent )
00439     {
00440         static typename BinarySearchTree::node * current;
00441         
00442         current = this->root;
00443         *parent = 0;
00444         this->direction = this->ROOT;
00445         
00446         if ( BinarySearchTree_size == 0 )
00447         {
00448             this->direction = this->NOT_FOUND;
00449             return current = 0;
00450         }
00451         
00452         // Check if the item is at the root
00453         if ( element == *( current->item ) )
00454         {
00455             this->direction = this->ROOT;
00456             return current;
00457         }
00458 
00459 #ifdef _MSC_VER
00460 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00461 #endif
00462         while ( true )
00463         {
00464             // Move pointer
00465             
00466             if ( element < *( current->item ) )
00467             {
00468                 *parent = current;
00469                 this->direction = this->LEFT;
00470                 current = current->left;
00471             }
00472             
00473             else
00474                 if ( element > *( current->item ) )
00475                 {
00476                     *parent = current;
00477                     this->direction = this->RIGHT;
00478                     current = current->right;
00479                 }
00480                 
00481             if ( current == 0 )
00482                 break;
00483                 
00484             // Check if new position holds the item
00485             if ( element == *( current->item ) )
00486             {
00487                 return current;
00488             }
00489         }
00490         
00491         
00492         this->direction = this->NOT_FOUND;
00493         return current = 0;
00494     }
00495     
00496     template <class BinarySearchTreeType>
00497     typename BinarySearchTree<BinarySearchTreeType>::node*& BinarySearchTree<BinarySearchTreeType>::FindParent( const BinarySearchTreeType& element )
00498     {
00499         static typename BinarySearchTree::node * parent;
00500         Find ( element, &parent );
00501         return parent;
00502     }
00503     
00504     // Performs a series of value swaps starting with current to fix the tree if needed
00505     template <class BinarySearchTreeType>
00506     void BinarySearchTree<BinarySearchTreeType>::FixTree( typename BinarySearchTree::node* current )
00507     {
00508         BinarySearchTreeType temp;
00509         
00510         while ( 1 )
00511         {
00512             if ( ( ( current->left ) != 0 ) && ( *( current->item ) < *( current->left->item ) ) )
00513             {
00514                 // Swap the current value with the one to the left
00515                 temp = *( current->left->item );
00516                 *( current->left->item ) = *( current->item );
00517                 *( current->item ) = temp;
00518                 current = current->left;
00519             }
00520             
00521             else
00522                 if ( ( ( current->right ) != 0 ) && ( *( current->item ) > *( current->right->item ) ) )
00523                 {
00524                     // Swap the current value with the one to the right
00525                     temp = *( current->right->item );
00526                     *( current->right->item ) = *( current->item );
00527                     *( current->item ) = temp;
00528                     current = current->right;
00529                 }
00530                 
00531                 else
00532                     break;  // current points to the right place so quit
00533         }
00534     }
00535     
00536     template <class BinarySearchTreeType>
00537     typename BinarySearchTree<BinarySearchTreeType>::node* BinarySearchTree<BinarySearchTreeType>::Del( const BinarySearchTreeType& input, const char *file, unsigned int line )
00538     {
00539         typename BinarySearchTree::node * node_to_delete, *current, *parent;
00540         
00541         if ( BinarySearchTree_size == 0 )
00542             return 0;
00543             
00544         if ( BinarySearchTree_size == 1 )
00545         {
00546             Clear(file, line);
00547             return 0;
00548         }
00549         
00550         node_to_delete = Find( input, &parent );
00551         
00552         if ( direction == NOT_FOUND )
00553             return 0;  // Couldn't find the element
00554             
00555         current = node_to_delete;
00556         
00557         // Replace the deleted node with the appropriate value
00558         if ( ( current->right ) == 0 && ( current->left ) == 0 )    // Leaf node, just remove it
00559         {
00560         
00561             if ( parent )
00562             {
00563                 if ( direction == LEFT )
00564                     parent->left = 0;
00565                 else
00566                     parent->right = 0;
00567             }
00568             
00569             RakNet::OP_DELETE(node_to_delete->item, file, line);
00570             RakNet::OP_DELETE(node_to_delete, file, line);
00571             BinarySearchTree_size--;
00572             return parent;
00573         }
00574         else
00575             if ( ( current->right ) != 0 && ( current->left ) == 0 )   // Node has only one child, delete it and cause the parent to point to that child
00576             {
00577             
00578                 if ( parent )
00579                 {
00580                     if ( direction == RIGHT )
00581                         parent->right = current->right;
00582                     else
00583                         parent->left = current->right;
00584                 }
00585                 
00586                 else
00587                     root = current->right; // Without a parent this must be the root node
00588                     
00589                 RakNet::OP_DELETE(node_to_delete->item, file, line);
00590                 
00591                 RakNet::OP_DELETE(node_to_delete, file, line);
00592                 
00593                 BinarySearchTree_size--;
00594                 
00595                 return parent;
00596             }
00597             else
00598                 if ( ( current->right ) == 0 && ( current->left ) != 0 )   // Node has only one child, delete it and cause the parent to point to that child
00599                 {
00600                 
00601                     if ( parent )
00602                     {
00603                         if ( direction == RIGHT )
00604                             parent->right = current->left;
00605                         else
00606                             parent->left = current->left;
00607                     }
00608                     
00609                     else
00610                         root = current->left; // Without a parent this must be the root node
00611                         
00612                     RakNet::OP_DELETE(node_to_delete->item, file, line);
00613                     
00614                     RakNet::OP_DELETE(node_to_delete, file, line);
00615                     
00616                     BinarySearchTree_size--;
00617                     
00618                     return parent;
00619                 }
00620                 else // Go right, then as left as far as you can
00621                 {
00622                     parent = current;
00623                     direction = RIGHT;
00624                     current = current->right; // Must have a right branch because the if statements above indicated that it has 2 branches
00625                     
00626                     while ( current->left )
00627                     {
00628                         direction = LEFT;
00629                         parent = current;
00630                         current = current->left;
00631                     }
00632                     
00633                     // Replace the value held by the node to RakNet::OP_DELETE(with the value pointed to by current, _FILE_AND_LINE_);
00634                     *( node_to_delete->item ) = *( current->item );
00635                     
00636                     // Delete current.
00637                     // If it is a leaf node just delete it
00638                     if ( current->right == 0 )
00639                     {
00640                         if ( direction == RIGHT )
00641                             parent->right = 0;
00642                         else
00643                             parent->left = 0;
00644                             
00645                         RakNet::OP_DELETE(current->item, file, line);
00646                         
00647                         RakNet::OP_DELETE(current, file, line);
00648                         
00649                         BinarySearchTree_size--;
00650                         
00651                         return parent;
00652                     }
00653                     
00654                     else
00655                     {
00656                         // Skip this node and make its parent point to its right branch
00657                         
00658                         if ( direction == RIGHT )
00659                             parent->right = current->right;
00660                         else
00661                             parent->left = current->right;
00662                             
00663                         RakNet::OP_DELETE(current->item, file, line);
00664                         
00665                         RakNet::OP_DELETE(current, file, line);
00666                         
00667                         BinarySearchTree_size--;
00668                         
00669                         return parent;
00670                     }
00671                 }
00672     }
00673     
00674     template <class BinarySearchTreeType>
00675     typename BinarySearchTree<BinarySearchTreeType>::node* BinarySearchTree<BinarySearchTreeType>::Add ( const BinarySearchTreeType& input, const char *file, unsigned int line )
00676     {
00677         typename BinarySearchTree::node * current;
00678         
00679         // Add the new element to the tree according to the following alogrithm:
00680         // 1.  If the current node is empty add the new leaf
00681         // 2.  If the element is less than the current node then go down the left branch
00682         // 3.  If the element is greater than the current node then go down the right branch
00683         
00684         if ( BinarySearchTree_size == 0 )
00685         {
00686             BinarySearchTree_size = 1;
00687             root = RakNet::OP_NEW<typename BinarySearchTree::node>( file, line );
00688             root->item = RakNet::OP_NEW<BinarySearchTreeType>( file, line );
00689             *( root->item ) = input;
00690             root->left = 0;
00691             root->right = 0;
00692             
00693             return root;
00694         }
00695         
00696         else
00697         {
00698             // start at the root
00699             current = root;
00700 
00701 #ifdef _MSC_VER
00702 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00703 #endif
00704             while ( true )    // This loop traverses the tree to find a spot for insertion
00705             {
00706             
00707                 if ( input < *( current->item ) )
00708                 {
00709                     if ( current->left == 0 )
00710                     {
00711                         current->left = RakNet::OP_NEW<typename BinarySearchTree::node>( file, line );
00712                         current->left->item = RakNet::OP_NEW<BinarySearchTreeType>( file, line );
00713                         current = current->left;
00714                         current->left = 0;
00715                         current->right = 0;
00716                         *( current->item ) = input;
00717                         
00718                         BinarySearchTree_size++;
00719                         return current;
00720                     }
00721                     
00722                     else
00723                     {
00724                         current = current->left;
00725                     }
00726                 }
00727                 
00728                 else
00729                     if ( input > *( current->item ) )
00730                     {
00731                         if ( current->right == 0 )
00732                         {
00733                             current->right = RakNet::OP_NEW<typename BinarySearchTree::node>( file, line );
00734                             current->right->item = RakNet::OP_NEW<BinarySearchTreeType>( file, line );
00735                             current = current->right;
00736                             current->left = 0;
00737                             current->right = 0;
00738                             *( current->item ) = input;
00739                             
00740                             BinarySearchTree_size++;
00741                             return current;
00742                         }
00743                         
00744                         else
00745                         {
00746                             current = current->right;
00747                         }
00748                     }
00749                     
00750                     else
00751                         return 0; // ((input == current->item) == true) which is not allowed since the tree only takes discrete values.  Do nothing
00752             }
00753         }
00754     }
00755     
00756     template <class BinarySearchTreeType>
00757     bool BinarySearchTree<BinarySearchTreeType>::IsIn( const BinarySearchTreeType& input )
00758     {
00759         typename BinarySearchTree::node * parent;
00760         find( input, &parent );
00761         
00762         if ( direction != NOT_FOUND )
00763             return true;
00764         else
00765             return false;
00766     }
00767     
00768     
00769     template <class BinarySearchTreeType>
00770     void BinarySearchTree<BinarySearchTreeType>::DisplayInorder( BinarySearchTreeType* return_array )
00771     {
00772         typename BinarySearchTree::node * current, *parent;
00773         bool just_printed = false;
00774         
00775         unsigned int index = 0;
00776         
00777         current = root;
00778         
00779         if ( BinarySearchTree_size == 0 )
00780             return ; // Do nothing for an empty tree
00781             
00782         else
00783             if ( BinarySearchTree_size == 1 )
00784             {
00785                 return_array[ 0 ] = *( root->item );
00786                 return ;
00787             }
00788             
00789             
00790         direction = ROOT;  // Reset the direction
00791         
00792         while ( index != BinarySearchTree_size )
00793         {
00794             // direction is set by the find function and holds the direction of the parent to the last node visited.  It is used to prevent revisiting nodes
00795             
00796             if ( ( current->left != 0 ) && ( direction != LEFT ) && ( direction != RIGHT ) )
00797             {
00798                 //  Go left if the following 2 conditions are true
00799                 //  I can go left
00800                 //  I did not just move up from a right child
00801                 //  I did not just move up from a left child
00802                 
00803                 current = current->left;
00804                 direction = ROOT;  // Reset the direction
00805             }
00806             
00807             else
00808                 if ( ( direction != RIGHT ) && ( just_printed == false ) )
00809                 {
00810                     // Otherwise, print the current node if the following 3 conditions are true:
00811                     // I did not just move up from a right child
00812                     // I did not print this ndoe last cycle
00813                     
00814                     return_array[ index++ ] = *( current->item );
00815                     just_printed = true;
00816                 }
00817                 
00818                 else
00819                     if ( ( current->right != 0 ) && ( direction != RIGHT ) )
00820                     {
00821                         // Otherwise, go right if the following 2 conditions are true
00822                         // I did not just move up from a right child
00823                         // I can go right
00824                         
00825                         current = current->right;
00826                         direction = ROOT;  // Reset the direction
00827                         just_printed = false;
00828                     }
00829                     
00830                     else
00831                     {
00832                         //  Otherwise I've done everything I can.  Move up the tree one node
00833                         parent = FindParent( *( current->item ) );
00834                         current = parent;
00835                         just_printed = false;
00836                     }
00837         }
00838     }
00839     
00840     template <class BinarySearchTreeType>
00841     void BinarySearchTree<BinarySearchTreeType>::DisplayPreorder( BinarySearchTreeType* return_array )
00842     {
00843         typename BinarySearchTree::node * current, *parent;
00844         
00845         unsigned int index = 0;
00846         
00847         current = root;
00848         
00849         if ( BinarySearchTree_size == 0 )
00850             return ; // Do nothing for an empty tree
00851             
00852         else
00853             if ( BinarySearchTree_size == 1 )
00854             {
00855                 return_array[ 0 ] = *( root->item );
00856                 return ;
00857             }
00858             
00859             
00860         direction = ROOT;  // Reset the direction
00861         return_array[ index++ ] = *( current->item );
00862         
00863         while ( index != BinarySearchTree_size )
00864         {
00865             // direction is set by the find function and holds the direction of the parent to the last node visited.  It is used to prevent revisiting nodes
00866             
00867             if ( ( current->left != 0 ) && ( direction != LEFT ) && ( direction != RIGHT ) )
00868             {
00869             
00870                 current = current->left;
00871                 direction = ROOT;
00872                 
00873                 // Everytime you move a node print it
00874                 return_array[ index++ ] = *( current->item );
00875             }
00876             
00877             else
00878                 if ( ( current->right != 0 ) && ( direction != RIGHT ) )
00879                 {
00880                     current = current->right;
00881                     direction = ROOT;
00882                     
00883                     // Everytime you move a node print it
00884                     return_array[ index++ ] = *( current->item );
00885                 }
00886                 
00887                 else
00888                 {
00889                     //  Otherwise I've done everything I can.  Move up the tree one node
00890                     parent = FindParent( *( current->item ) );
00891                     current = parent;
00892                 }
00893         }
00894     }
00895     
00896     template <class BinarySearchTreeType>
00897     inline void BinarySearchTree<BinarySearchTreeType>::DisplayPostorder( BinarySearchTreeType* return_array )
00898     {
00899         unsigned int index = 0;
00900         
00901         if ( BinarySearchTree_size == 0 )
00902             return ; // Do nothing for an empty tree
00903             
00904         else
00905             if ( BinarySearchTree_size == 1 )
00906             {
00907                 return_array[ 0 ] = *( root->item );
00908                 return ;
00909             }
00910             
00911         DisplayPostorderRecursive( root, return_array, index );
00912     }
00913     
00914     
00915     // Recursively do a postorder traversal
00916     template <class BinarySearchTreeType>
00917     void BinarySearchTree<BinarySearchTreeType>::DisplayPostorderRecursive( typename BinarySearchTree::node* current, BinarySearchTreeType* return_array, unsigned int& index )
00918     {
00919         if ( current->left != 0 )
00920             DisplayPostorderRecursive( current->left, return_array, index );
00921             
00922         if ( current->right != 0 )
00923             DisplayPostorderRecursive( current->right, return_array, index );
00924             
00925         return_array[ index++ ] = *( current->item );
00926         
00927     }
00928     
00929     
00930     template <class BinarySearchTreeType>
00931     void BinarySearchTree<BinarySearchTreeType>::DisplayBreadthFirstSearch( BinarySearchTreeType* return_array )
00932     {
00933         typename BinarySearchTree::node * current;
00934         unsigned int index = 0;
00935         
00936         // Display the tree using a breadth first search
00937         // Put the children of the current node into the queue
00938         // Pop the queue, put its children into the queue, repeat until queue is empty
00939         
00940         if ( BinarySearchTree_size == 0 )
00941             return ; // Do nothing for an empty tree
00942             
00943         else
00944             if ( BinarySearchTree_size == 1 )
00945             {
00946                 return_array[ 0 ] = *( root->item );
00947                 return ;
00948             }
00949             
00950             else
00951             {
00952                 DataStructures::QueueLinkedList<node *> tree_queue;
00953                 
00954                 // Add the root of the tree I am copying from
00955                 tree_queue.Push( root );
00956                 
00957                 do
00958                 {
00959                     current = tree_queue.Pop();
00960                     return_array[ index++ ] = *( current->item );
00961                     
00962                     // Add the child or children of the tree I am copying from to the queue
00963                     
00964                     if ( current->left != 0 )
00965                         tree_queue.Push( current->left );
00966                         
00967                     if ( current->right != 0 )
00968                         tree_queue.Push( current->right );
00969                         
00970                 }
00971                 
00972                 while ( tree_queue.Size() > 0 );
00973             }
00974     }
00975     
00976     
00977     template <class BinarySearchTreeType>
00978     BinarySearchTree<BinarySearchTreeType>::BinarySearchTree( const BinarySearchTree& original_copy )
00979     {
00980         typename BinarySearchTree::node * current;
00981         // Copy the tree using a breadth first search
00982         // Put the children of the current node into the queue
00983         // Pop the queue, put its children into the queue, repeat until queue is empty
00984         
00985         // This is a copy of the constructor.  A bug in Visual C++ made it so if I just put the constructor call here the variable assignments were ignored.
00986         BinarySearchTree_size = 0;
00987         root = 0;
00988         
00989         if ( original_copy.BinarySearchTree_size == 0 )
00990         {
00991             BinarySearchTree_size = 0;
00992         }
00993         
00994         else
00995         {
00996             DataStructures::QueueLinkedList<node *> tree_queue;
00997             
00998             // Add the root of the tree I am copying from
00999             tree_queue.Push( original_copy.root );
01000             
01001             do
01002             {
01003                 current = tree_queue.Pop();
01004                 
01005                 Add ( *( current->item ), _FILE_AND_LINE_ )
01006                 
01007                 ;
01008                 
01009                 // Add the child or children of the tree I am copying from to the queue
01010                 if ( current->left != 0 )
01011                     tree_queue.Push( current->left );
01012                     
01013                 if ( current->right != 0 )
01014                     tree_queue.Push( current->right );
01015                     
01016             }
01017             
01018             while ( tree_queue.Size() > 0 );
01019         }
01020     }
01021     
01022     template <class BinarySearchTreeType>
01023     BinarySearchTree<BinarySearchTreeType>& BinarySearchTree<BinarySearchTreeType>::operator= ( const BinarySearchTree& original_copy )
01024     {
01025         typename BinarySearchTree::node * current;
01026         
01027         if ( ( &original_copy ) == this )
01028             return *this;
01029             
01030         Clear( _FILE_AND_LINE_ );  // Remove the current tree
01031         
01032         // This is a copy of the constructor.  A bug in Visual C++ made it so if I just put the constructor call here the variable assignments were ignored.
01033         BinarySearchTree_size = 0;
01034         
01035         root = 0;
01036         
01037         
01038         // Copy the tree using a breadth first search
01039         // Put the children of the current node into the queue
01040         // Pop the queue, put its children into the queue, repeat until queue is empty
01041         if ( original_copy.BinarySearchTree_size == 0 )
01042         {
01043             BinarySearchTree_size = 0;
01044         }
01045         
01046         else
01047         {
01048             DataStructures::QueueLinkedList<node *> tree_queue;
01049             
01050             // Add the root of the tree I am copying from
01051             tree_queue.Push( original_copy.root );
01052             
01053             do
01054             {
01055                 current = tree_queue.Pop();
01056                 
01057                 Add ( *( current->item ), _FILE_AND_LINE_ )
01058                 
01059                 ;
01060                 
01061                 // Add the child or children of the tree I am copying from to the queue
01062                 if ( current->left != 0 )
01063                     tree_queue.Push( current->left );
01064                     
01065                 if ( current->right != 0 )
01066                     tree_queue.Push( current->right );
01067                     
01068             }
01069             
01070             while ( tree_queue.Size() > 0 );
01071         }
01072         
01073         return *this;
01074     }
01075     
01076     template <class BinarySearchTreeType>
01077     inline void BinarySearchTree<BinarySearchTreeType>::Clear ( const char *file, unsigned int line )
01078     {
01079         typename BinarySearchTree::node * current, *parent;
01080         
01081         current = root;
01082         
01083         while ( BinarySearchTree_size > 0 )
01084         {
01085             if ( BinarySearchTree_size == 1 )
01086             {
01087                 RakNet::OP_DELETE(root->item, file, line);
01088                 RakNet::OP_DELETE(root, file, line);
01089                 root = 0;
01090                 BinarySearchTree_size = 0;
01091             }
01092             
01093             else
01094             {
01095                 if ( current->left != 0 )
01096                 {
01097                     current = current->left;
01098                 }
01099                 
01100                 else
01101                     if ( current->right != 0 )
01102                     {
01103                         current = current->right;
01104                     }
01105                     
01106                     else // leaf
01107                     {
01108                         // Not root node so must have a parent
01109                         parent = FindParent( *( current->item ) );
01110                         
01111                         if ( ( parent->left ) == current )
01112                             parent->left = 0;
01113                         else
01114                             parent->right = 0;
01115                             
01116                         RakNet::OP_DELETE(current->item, file, line);
01117                         
01118                         RakNet::OP_DELETE(current, file, line);
01119                         
01120                         current = parent;
01121                         
01122                         BinarySearchTree_size--;
01123                     }
01124             }
01125         }
01126     }
01127     
01128 } // End namespace
01129 
01130 #endif
01131 
01132 #ifdef _MSC_VER
01133 #pragma warning( pop )
01134 #endif

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net