• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

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__,__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__,__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__,__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__,__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__, __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__, __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__, __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__, __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

Generated on Thu Sep 30 2010 01:27:22 for RakNet by  doxygen 1.7.1