| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- /// \file DS_BinarySearchTree.h
- /// \internal
- /// \brief A binary search tree, and an AVL balanced BST derivation.
- ///
- #ifndef __BINARY_SEARCH_TREE_H
- #define __BINARY_SEARCH_TREE_H
- #include "DS_QueueLinkedList.h"
- #include "RakMemoryOverride.h"
- #include "Export.h"
- #ifdef _MSC_VER
- #pragma warning( push )
- #endif
- /// The namespace DataStructures was only added to avoid compiler errors for commonly named data structures
- /// As these data structures are stand-alone, you can use them outside of RakNet for your own projects if you wish.
- namespace DataStructures
- {
- /**
- * \brief A binary search tree and an AVL balanced binary search tree.
- * \details
- * Initilize with the following structure
- *
- * BinarySearchTree<TYPE>
- *
- * OR
- *
- * AVLBalancedBinarySearchTree<TYPE>
- *
- * Use the AVL balanced tree if you want the tree to be balanced after every deletion and addition. This avoids the potential
- * worst case scenario where ordered input to a binary search tree gives linear search time results. It's not needed
- * if input will be evenly distributed, in which case the search time is O (log n). The search time for the AVL
- * balanced binary tree is O (log n) irregardless of input.
- *
- * Has the following member functions
- * unsigned int Height(<index>) - Returns the height of the tree at the optional specified starting index. Default is the root
- * add(element) - adds an element to the BinarySearchTree
- * bool del(element) - deletes the node containing element if the element is in the tree as defined by a comparison with the == operator. Returns true on success, false if the element is not found
- * bool IsInelement) - returns true if element is in the tree as defined by a comparison with the == operator. Otherwise returns false
- * DisplayInorder(array) - Fills an array with an inorder search of the elements in the tree. USER IS REPONSIBLE FOR ALLOCATING THE ARRAY!.
- * DisplayPreorder(array) - Fills an array with an preorder search of the elements in the tree. USER IS REPONSIBLE FOR ALLOCATING THE ARRAY!.
- * DisplayPostorder(array) - Fills an array with an postorder search of the elements in the tree. USER IS REPONSIBLE FOR ALLOCATING THE ARRAY!.
- * DisplayBreadthFirstSearch(array) - Fills an array with a breadth first search of the elements in the tree. USER IS REPONSIBLE FOR ALLOCATING THE ARRAY!.
- * clear - Destroys the tree. Same as calling the destructor
- * unsigned int Height() - Returns the height of the tree
- * unsigned int size() - returns the size of the BinarySearchTree
- * GetPointerToNode(element) - returns a pointer to the comparision element in the tree, allowing for direct modification when necessary with complex data types.
- * Be warned, it is possible to corrupt the tree if the element used for comparisons is modified. Returns NULL if the item is not found
- *
- *
- * EXAMPLE
- * @code
- * BinarySearchTree<int> A;
- * A.Add(10);
- * A.Add(15);
- * A.Add(5);
- * int* array = RakNet::OP_NEW<int >(A.Size(), _FILE_AND_LINE_ );
- * A.DisplayInorder(array);
- * array[0]; // returns 5
- * array[1]; // returns 10
- * array[2]; // returns 15
- * @endcode
- * compress - reallocates memory to fit the number of elements. Best used when the number of elements decreases
- *
- * clear - empties the BinarySearchTree and returns storage
- * The assignment and copy constructors are defined
- *
- * \note The template type must have the copy constructor and
- * assignment operator defined and must work with >, <, and == All
- * elements in the tree MUST be distinct The assignment operator is
- * defined between BinarySearchTree and AVLBalancedBinarySearchTree
- * as long as they are of the same template type. However, passing a
- * BinarySearchTree to an AVLBalancedBinarySearchTree will lose its
- * structure unless it happened to be AVL balanced to begin with
- * Requires queue_linked_list.cpp for the breadth first search used
- * in the copy constructor, overloaded assignment operator, and
- * display_breadth_first_search.
- *
- *
- */
- template <class BinarySearchTreeType>
- class RAK_DLL_EXPORT BinarySearchTree
- {
-
- public:
- struct node
- {
- BinarySearchTreeType* item;
- node* left;
- node* right;
- };
-
- BinarySearchTree();
- virtual ~BinarySearchTree();
- BinarySearchTree( const BinarySearchTree& original_type );
- BinarySearchTree& operator= ( const BinarySearchTree& original_copy );
- unsigned int Size( void );
- void Clear( const char *file, unsigned int line );
- unsigned int Height( node* starting_node = 0 );
- node* Add ( const BinarySearchTreeType& input, const char *file, unsigned int line );
- node* Del( const BinarySearchTreeType& input, const char *file, unsigned int line );
- bool IsIn( const BinarySearchTreeType& input );
- void DisplayInorder( BinarySearchTreeType* return_array );
- void DisplayPreorder( BinarySearchTreeType* return_array );
- void DisplayPostorder( BinarySearchTreeType* return_array );
- void DisplayBreadthFirstSearch( BinarySearchTreeType* return_array );
- BinarySearchTreeType*& GetPointerToNode( const BinarySearchTreeType& element );
-
- protected:
- node* root;
-
- enum Direction_Types
- {
- NOT_FOUND, LEFT, RIGHT, ROOT
- } direction;
- unsigned int HeightRecursive( node* current );
- unsigned int BinarySearchTree_size;
- node*& Find( const BinarySearchTreeType& element, node** parent );
- node*& FindParent( const BinarySearchTreeType& element );
- void DisplayPostorderRecursive( node* current, BinarySearchTreeType* return_array, unsigned int& index );
- void FixTree( node* current );
-
- };
-
- /// An AVLBalancedBinarySearchTree is a binary tree that is always balanced
- template <class BinarySearchTreeType>
- class RAK_DLL_EXPORT AVLBalancedBinarySearchTree : public BinarySearchTree<BinarySearchTreeType>
- {
-
- public:
- AVLBalancedBinarySearchTree() {}
- virtual ~AVLBalancedBinarySearchTree();
- void Add ( const BinarySearchTreeType& input );
- void Del( const BinarySearchTreeType& input );
- BinarySearchTree<BinarySearchTreeType>& operator= ( BinarySearchTree<BinarySearchTreeType>& original_copy )
- {
- return BinarySearchTree<BinarySearchTreeType>::operator= ( original_copy );
- }
-
- private:
- void BalanceTree( typename BinarySearchTree<BinarySearchTreeType>::node* current, bool rotateOnce );
- void RotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *C );
- void RotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node* C );
- void DoubleRotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *A );
- void DoubleRotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node* A );
- bool RightHigher( typename BinarySearchTree<BinarySearchTreeType>::node* A );
- bool LeftHigher( typename BinarySearchTree<BinarySearchTreeType>::node* A );
- };
-
- template <class BinarySearchTreeType>
- void AVLBalancedBinarySearchTree<BinarySearchTreeType>::BalanceTree( typename BinarySearchTree<BinarySearchTreeType>::node* current, bool rotateOnce )
- {
- int left_height, right_height;
-
- while ( current )
- {
- if ( current->left == 0 )
- left_height = 0;
- else
- left_height = Height( current->left );
-
- if ( current->right == 0 )
- right_height = 0;
- else
- right_height = Height( current->right );
-
- if ( right_height - left_height == 2 )
- {
- if ( RightHigher( current->right ) )
- RotateLeft( current->right );
- else
- DoubleRotateLeft( current );
-
- if ( rotateOnce )
- break;
- }
-
- else
- if ( right_height - left_height == -2 )
- {
- if ( LeftHigher( current->left ) )
- RotateRight( current->left );
- else
- DoubleRotateRight( current );
-
- if ( rotateOnce )
- break;
- }
-
- if ( current == this->root )
- break;
-
- current = FindParent( *( current->item ) );
-
- }
- }
-
- template <class BinarySearchTreeType>
- void AVLBalancedBinarySearchTree<BinarySearchTreeType>::Add ( const BinarySearchTreeType& input )
- {
-
- typename BinarySearchTree<BinarySearchTreeType>::node * current = BinarySearchTree<BinarySearchTreeType>::Add ( input, _FILE_AND_LINE_ );
- BalanceTree( current, true );
- }
-
- template <class BinarySearchTreeType>
- void AVLBalancedBinarySearchTree<BinarySearchTreeType>::Del( const BinarySearchTreeType& input )
- {
- typename BinarySearchTree<BinarySearchTreeType>::node * current = BinarySearchTree<BinarySearchTreeType>::Del( input, _FILE_AND_LINE_ );
- BalanceTree( current, false );
-
- }
-
- template <class BinarySearchTreeType>
- bool AVLBalancedBinarySearchTree<BinarySearchTreeType>::RightHigher( typename BinarySearchTree<BinarySearchTreeType>::node *A )
- {
- if ( A == 0 )
- return false;
-
- return Height( A->right ) > Height( A->left );
- }
-
- template <class BinarySearchTreeType>
- bool AVLBalancedBinarySearchTree<BinarySearchTreeType>::LeftHigher( typename BinarySearchTree<BinarySearchTreeType>::node *A )
- {
- if ( A == 0 )
- return false;
-
- return Height( A->left ) > Height( A->right );
- }
-
- template <class BinarySearchTreeType>
- void AVLBalancedBinarySearchTree<BinarySearchTreeType>::RotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *C )
- {
- typename BinarySearchTree<BinarySearchTreeType>::node * A, *B, *D;
- /*
- RIGHT ROTATION
-
- A = parent(b)
- b= parent(c)
- c = node to rotate around
-
- A
- | // Either direction
- B
- / \
- C
- / \
- D
-
- TO
-
- A
- | // Either Direction
- C
- / \
- B
- / \
- D
-
-
- <Leave all other branches branches AS-IS whether they point to another node or simply 0>
-
- */
-
- B = FindParent( *( C->item ) );
- A = FindParent( *( B->item ) );
- D = C->right;
-
- if ( A )
- {
- // Direction was set by the last find_parent call
-
- if ( this->direction == this->LEFT )
- A->left = C;
- else
- A->right = C;
- }
-
- else
- this->root = C; // If B has no parent parent then B must have been the root node
-
- B->left = D;
-
- C->right = B;
- }
-
- template <class BinarySearchTreeType>
- void AVLBalancedBinarySearchTree<BinarySearchTreeType>::DoubleRotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *A )
- {
- // 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.
- RotateLeft( A->left->right );
- RotateRight( A->left );
- }
-
- template <class BinarySearchTreeType>
- void AVLBalancedBinarySearchTree<BinarySearchTreeType>::RotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node *C )
- {
- typename BinarySearchTree<BinarySearchTreeType>::node * A, *B, *D;
- /*
- RIGHT ROTATION
-
- A = parent(b)
- b= parent(c)
- c = node to rotate around
-
- A
- | // Either direction
- B
- / \
- C
- / \
- D
-
- TO
-
- A
- | // Either Direction
- C
- / \
- B
- / \
- D
-
-
- <Leave all other branches branches AS-IS whether they point to another node or simply 0>
-
- */
-
- B = FindParent( *( C->item ) );
- A = FindParent( *( B->item ) );
- D = C->left;
-
- if ( A )
- {
- // Direction was set by the last find_parent call
-
- if ( this->direction == this->LEFT )
- A->left = C;
- else
- A->right = C;
- }
-
- else
- this->root = C; // If B has no parent parent then B must have been the root node
-
- B->right = D;
-
- C->left = B;
- }
-
- template <class BinarySearchTreeType>
- void AVLBalancedBinarySearchTree<BinarySearchTreeType>::DoubleRotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node *A )
- {
- // 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.
- RotateRight( A->right->left );
- RotateLeft( A->right );
- }
-
- template <class BinarySearchTreeType>
- AVLBalancedBinarySearchTree<BinarySearchTreeType>::~AVLBalancedBinarySearchTree()
- {
- this->Clear(_FILE_AND_LINE_);
- }
-
- template <class BinarySearchTreeType>
- unsigned int BinarySearchTree<BinarySearchTreeType>::Size( void )
- {
- return BinarySearchTree_size;
- }
-
- template <class BinarySearchTreeType>
- unsigned int BinarySearchTree<BinarySearchTreeType>::Height( typename BinarySearchTree::node* starting_node )
- {
- if ( BinarySearchTree_size == 0 || starting_node == 0 )
- return 0;
- else
- return HeightRecursive( starting_node );
- }
-
- // Recursively return the height of a binary tree
- template <class BinarySearchTreeType>
- unsigned int BinarySearchTree<BinarySearchTreeType>::HeightRecursive( typename BinarySearchTree::node* current )
- {
- unsigned int left_height = 0, right_height = 0;
-
- if ( ( current->left == 0 ) && ( current->right == 0 ) )
- return 1; // Leaf
-
- if ( current->left != 0 )
- left_height = 1 + HeightRecursive( current->left );
-
- if ( current->right != 0 )
- right_height = 1 + HeightRecursive( current->right );
-
- if ( left_height > right_height )
- return left_height;
- else
- return right_height;
- }
-
- template <class BinarySearchTreeType>
- BinarySearchTree<BinarySearchTreeType>::BinarySearchTree()
- {
- BinarySearchTree_size = 0;
- root = 0;
- }
-
- template <class BinarySearchTreeType>
- BinarySearchTree<BinarySearchTreeType>::~BinarySearchTree()
- {
- this->Clear(_FILE_AND_LINE_);
- }
-
- template <class BinarySearchTreeType>
- BinarySearchTreeType*& BinarySearchTree<BinarySearchTreeType>::GetPointerToNode( const BinarySearchTreeType& element )
- {
- static typename BinarySearchTree::node * tempnode;
- static BinarySearchTreeType* dummyptr = 0;
- tempnode = Find ( element, &tempnode );
-
- if ( this->direction == this->NOT_FOUND )
- return dummyptr;
-
- return tempnode->item;
- }
-
- template <class BinarySearchTreeType>
- typename BinarySearchTree<BinarySearchTreeType>::node*& BinarySearchTree<BinarySearchTreeType>::Find( const BinarySearchTreeType& element, typename BinarySearchTree<BinarySearchTreeType>::node** parent )
- {
- static typename BinarySearchTree::node * current;
-
- current = this->root;
- *parent = 0;
- this->direction = this->ROOT;
-
- if ( BinarySearchTree_size == 0 )
- {
- this->direction = this->NOT_FOUND;
- return current = 0;
- }
-
- // Check if the item is at the root
- if ( element == *( current->item ) )
- {
- this->direction = this->ROOT;
- return current;
- }
- #ifdef _MSC_VER
- #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
- #endif
- while ( true )
- {
- // Move pointer
-
- if ( element < *( current->item ) )
- {
- *parent = current;
- this->direction = this->LEFT;
- current = current->left;
- }
-
- else
- if ( element > *( current->item ) )
- {
- *parent = current;
- this->direction = this->RIGHT;
- current = current->right;
- }
-
- if ( current == 0 )
- break;
-
- // Check if new position holds the item
- if ( element == *( current->item ) )
- {
- return current;
- }
- }
-
-
- this->direction = this->NOT_FOUND;
- return current = 0;
- }
-
- template <class BinarySearchTreeType>
- typename BinarySearchTree<BinarySearchTreeType>::node*& BinarySearchTree<BinarySearchTreeType>::FindParent( const BinarySearchTreeType& element )
- {
- static typename BinarySearchTree::node * parent;
- Find ( element, &parent );
- return parent;
- }
-
- // Performs a series of value swaps starting with current to fix the tree if needed
- template <class BinarySearchTreeType>
- void BinarySearchTree<BinarySearchTreeType>::FixTree( typename BinarySearchTree::node* current )
- {
- BinarySearchTreeType temp;
-
- while ( 1 )
- {
- if ( ( ( current->left ) != 0 ) && ( *( current->item ) < *( current->left->item ) ) )
- {
- // Swap the current value with the one to the left
- temp = *( current->left->item );
- *( current->left->item ) = *( current->item );
- *( current->item ) = temp;
- current = current->left;
- }
-
- else
- if ( ( ( current->right ) != 0 ) && ( *( current->item ) > *( current->right->item ) ) )
- {
- // Swap the current value with the one to the right
- temp = *( current->right->item );
- *( current->right->item ) = *( current->item );
- *( current->item ) = temp;
- current = current->right;
- }
-
- else
- break; // current points to the right place so quit
- }
- }
-
- template <class BinarySearchTreeType>
- typename BinarySearchTree<BinarySearchTreeType>::node* BinarySearchTree<BinarySearchTreeType>::Del( const BinarySearchTreeType& input, const char *file, unsigned int line )
- {
- typename BinarySearchTree::node * node_to_delete, *current, *parent;
-
- if ( BinarySearchTree_size == 0 )
- return 0;
-
- if ( BinarySearchTree_size == 1 )
- {
- Clear(file, line);
- return 0;
- }
-
- node_to_delete = Find( input, &parent );
-
- if ( direction == NOT_FOUND )
- return 0; // Couldn't find the element
-
- current = node_to_delete;
-
- // Replace the deleted node with the appropriate value
- if ( ( current->right ) == 0 && ( current->left ) == 0 ) // Leaf node, just remove it
- {
-
- if ( parent )
- {
- if ( direction == LEFT )
- parent->left = 0;
- else
- parent->right = 0;
- }
-
- RakNet::OP_DELETE(node_to_delete->item, file, line);
- RakNet::OP_DELETE(node_to_delete, file, line);
- BinarySearchTree_size--;
- return parent;
- }
- else
- if ( ( current->right ) != 0 && ( current->left ) == 0 ) // Node has only one child, delete it and cause the parent to point to that child
- {
-
- if ( parent )
- {
- if ( direction == RIGHT )
- parent->right = current->right;
- else
- parent->left = current->right;
- }
-
- else
- root = current->right; // Without a parent this must be the root node
-
- RakNet::OP_DELETE(node_to_delete->item, file, line);
-
- RakNet::OP_DELETE(node_to_delete, file, line);
-
- BinarySearchTree_size--;
-
- return parent;
- }
- else
- if ( ( current->right ) == 0 && ( current->left ) != 0 ) // Node has only one child, delete it and cause the parent to point to that child
- {
-
- if ( parent )
- {
- if ( direction == RIGHT )
- parent->right = current->left;
- else
- parent->left = current->left;
- }
-
- else
- root = current->left; // Without a parent this must be the root node
-
- RakNet::OP_DELETE(node_to_delete->item, file, line);
-
- RakNet::OP_DELETE(node_to_delete, file, line);
-
- BinarySearchTree_size--;
-
- return parent;
- }
- else // Go right, then as left as far as you can
- {
- parent = current;
- direction = RIGHT;
- current = current->right; // Must have a right branch because the if statements above indicated that it has 2 branches
-
- while ( current->left )
- {
- direction = LEFT;
- parent = current;
- current = current->left;
- }
-
- // Replace the value held by the node to RakNet::OP_DELETE(with the value pointed to by current, _FILE_AND_LINE_);
- *( node_to_delete->item ) = *( current->item );
-
- // Delete current.
- // If it is a leaf node just delete it
- if ( current->right == 0 )
- {
- if ( direction == RIGHT )
- parent->right = 0;
- else
- parent->left = 0;
-
- RakNet::OP_DELETE(current->item, file, line);
-
- RakNet::OP_DELETE(current, file, line);
-
- BinarySearchTree_size--;
-
- return parent;
- }
-
- else
- {
- // Skip this node and make its parent point to its right branch
-
- if ( direction == RIGHT )
- parent->right = current->right;
- else
- parent->left = current->right;
-
- RakNet::OP_DELETE(current->item, file, line);
-
- RakNet::OP_DELETE(current, file, line);
-
- BinarySearchTree_size--;
-
- return parent;
- }
- }
- }
-
- template <class BinarySearchTreeType>
- typename BinarySearchTree<BinarySearchTreeType>::node* BinarySearchTree<BinarySearchTreeType>::Add ( const BinarySearchTreeType& input, const char *file, unsigned int line )
- {
- typename BinarySearchTree::node * current;
-
- // Add the new element to the tree according to the following alogrithm:
- // 1. If the current node is empty add the new leaf
- // 2. If the element is less than the current node then go down the left branch
- // 3. If the element is greater than the current node then go down the right branch
-
- if ( BinarySearchTree_size == 0 )
- {
- BinarySearchTree_size = 1;
- root = RakNet::OP_NEW<typename BinarySearchTree::node>( file, line );
- root->item = RakNet::OP_NEW<BinarySearchTreeType>( file, line );
- *( root->item ) = input;
- root->left = 0;
- root->right = 0;
-
- return root;
- }
-
- else
- {
- // start at the root
- current = root;
- #ifdef _MSC_VER
- #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
- #endif
- while ( true ) // This loop traverses the tree to find a spot for insertion
- {
-
- if ( input < *( current->item ) )
- {
- if ( current->left == 0 )
- {
- current->left = RakNet::OP_NEW<typename BinarySearchTree::node>( file, line );
- current->left->item = RakNet::OP_NEW<BinarySearchTreeType>( file, line );
- current = current->left;
- current->left = 0;
- current->right = 0;
- *( current->item ) = input;
-
- BinarySearchTree_size++;
- return current;
- }
-
- else
- {
- current = current->left;
- }
- }
-
- else
- if ( input > *( current->item ) )
- {
- if ( current->right == 0 )
- {
- current->right = RakNet::OP_NEW<typename BinarySearchTree::node>( file, line );
- current->right->item = RakNet::OP_NEW<BinarySearchTreeType>( file, line );
- current = current->right;
- current->left = 0;
- current->right = 0;
- *( current->item ) = input;
-
- BinarySearchTree_size++;
- return current;
- }
-
- else
- {
- current = current->right;
- }
- }
-
- else
- return 0; // ((input == current->item) == true) which is not allowed since the tree only takes discrete values. Do nothing
- }
- }
- }
-
- template <class BinarySearchTreeType>
- bool BinarySearchTree<BinarySearchTreeType>::IsIn( const BinarySearchTreeType& input )
- {
- typename BinarySearchTree::node * parent;
- find( input, &parent );
-
- if ( direction != NOT_FOUND )
- return true;
- else
- return false;
- }
-
-
- template <class BinarySearchTreeType>
- void BinarySearchTree<BinarySearchTreeType>::DisplayInorder( BinarySearchTreeType* return_array )
- {
- typename BinarySearchTree::node * current, *parent;
- bool just_printed = false;
-
- unsigned int index = 0;
-
- current = root;
-
- if ( BinarySearchTree_size == 0 )
- return ; // Do nothing for an empty tree
-
- else
- if ( BinarySearchTree_size == 1 )
- {
- return_array[ 0 ] = *( root->item );
- return ;
- }
-
-
- direction = ROOT; // Reset the direction
-
- while ( index != BinarySearchTree_size )
- {
- // 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
-
- if ( ( current->left != 0 ) && ( direction != LEFT ) && ( direction != RIGHT ) )
- {
- // Go left if the following 2 conditions are true
- // I can go left
- // I did not just move up from a right child
- // I did not just move up from a left child
-
- current = current->left;
- direction = ROOT; // Reset the direction
- }
-
- else
- if ( ( direction != RIGHT ) && ( just_printed == false ) )
- {
- // Otherwise, print the current node if the following 3 conditions are true:
- // I did not just move up from a right child
- // I did not print this ndoe last cycle
-
- return_array[ index++ ] = *( current->item );
- just_printed = true;
- }
-
- else
- if ( ( current->right != 0 ) && ( direction != RIGHT ) )
- {
- // Otherwise, go right if the following 2 conditions are true
- // I did not just move up from a right child
- // I can go right
-
- current = current->right;
- direction = ROOT; // Reset the direction
- just_printed = false;
- }
-
- else
- {
- // Otherwise I've done everything I can. Move up the tree one node
- parent = FindParent( *( current->item ) );
- current = parent;
- just_printed = false;
- }
- }
- }
-
- template <class BinarySearchTreeType>
- void BinarySearchTree<BinarySearchTreeType>::DisplayPreorder( BinarySearchTreeType* return_array )
- {
- typename BinarySearchTree::node * current, *parent;
-
- unsigned int index = 0;
-
- current = root;
-
- if ( BinarySearchTree_size == 0 )
- return ; // Do nothing for an empty tree
-
- else
- if ( BinarySearchTree_size == 1 )
- {
- return_array[ 0 ] = *( root->item );
- return ;
- }
-
-
- direction = ROOT; // Reset the direction
- return_array[ index++ ] = *( current->item );
-
- while ( index != BinarySearchTree_size )
- {
- // 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
-
- if ( ( current->left != 0 ) && ( direction != LEFT ) && ( direction != RIGHT ) )
- {
-
- current = current->left;
- direction = ROOT;
-
- // Everytime you move a node print it
- return_array[ index++ ] = *( current->item );
- }
-
- else
- if ( ( current->right != 0 ) && ( direction != RIGHT ) )
- {
- current = current->right;
- direction = ROOT;
-
- // Everytime you move a node print it
- return_array[ index++ ] = *( current->item );
- }
-
- else
- {
- // Otherwise I've done everything I can. Move up the tree one node
- parent = FindParent( *( current->item ) );
- current = parent;
- }
- }
- }
-
- template <class BinarySearchTreeType>
- inline void BinarySearchTree<BinarySearchTreeType>::DisplayPostorder( BinarySearchTreeType* return_array )
- {
- unsigned int index = 0;
-
- if ( BinarySearchTree_size == 0 )
- return ; // Do nothing for an empty tree
-
- else
- if ( BinarySearchTree_size == 1 )
- {
- return_array[ 0 ] = *( root->item );
- return ;
- }
-
- DisplayPostorderRecursive( root, return_array, index );
- }
-
-
- // Recursively do a postorder traversal
- template <class BinarySearchTreeType>
- void BinarySearchTree<BinarySearchTreeType>::DisplayPostorderRecursive( typename BinarySearchTree::node* current, BinarySearchTreeType* return_array, unsigned int& index )
- {
- if ( current->left != 0 )
- DisplayPostorderRecursive( current->left, return_array, index );
-
- if ( current->right != 0 )
- DisplayPostorderRecursive( current->right, return_array, index );
-
- return_array[ index++ ] = *( current->item );
-
- }
-
-
- template <class BinarySearchTreeType>
- void BinarySearchTree<BinarySearchTreeType>::DisplayBreadthFirstSearch( BinarySearchTreeType* return_array )
- {
- typename BinarySearchTree::node * current;
- unsigned int index = 0;
-
- // Display the tree using a breadth first search
- // Put the children of the current node into the queue
- // Pop the queue, put its children into the queue, repeat until queue is empty
-
- if ( BinarySearchTree_size == 0 )
- return ; // Do nothing for an empty tree
-
- else
- if ( BinarySearchTree_size == 1 )
- {
- return_array[ 0 ] = *( root->item );
- return ;
- }
-
- else
- {
- DataStructures::QueueLinkedList<node *> tree_queue;
-
- // Add the root of the tree I am copying from
- tree_queue.Push( root );
-
- do
- {
- current = tree_queue.Pop();
- return_array[ index++ ] = *( current->item );
-
- // Add the child or children of the tree I am copying from to the queue
-
- if ( current->left != 0 )
- tree_queue.Push( current->left );
-
- if ( current->right != 0 )
- tree_queue.Push( current->right );
-
- }
-
- while ( tree_queue.Size() > 0 );
- }
- }
-
-
- template <class BinarySearchTreeType>
- BinarySearchTree<BinarySearchTreeType>::BinarySearchTree( const BinarySearchTree& original_copy )
- {
- typename BinarySearchTree::node * current;
- // Copy the tree using a breadth first search
- // Put the children of the current node into the queue
- // Pop the queue, put its children into the queue, repeat until queue is empty
-
- // 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.
- BinarySearchTree_size = 0;
- root = 0;
-
- if ( original_copy.BinarySearchTree_size == 0 )
- {
- BinarySearchTree_size = 0;
- }
-
- else
- {
- DataStructures::QueueLinkedList<node *> tree_queue;
-
- // Add the root of the tree I am copying from
- tree_queue.Push( original_copy.root );
-
- do
- {
- current = tree_queue.Pop();
-
- Add ( *( current->item ), _FILE_AND_LINE_ )
-
- ;
-
- // Add the child or children of the tree I am copying from to the queue
- if ( current->left != 0 )
- tree_queue.Push( current->left );
-
- if ( current->right != 0 )
- tree_queue.Push( current->right );
-
- }
-
- while ( tree_queue.Size() > 0 );
- }
- }
-
- template <class BinarySearchTreeType>
- BinarySearchTree<BinarySearchTreeType>& BinarySearchTree<BinarySearchTreeType>::operator= ( const BinarySearchTree& original_copy )
- {
- typename BinarySearchTree::node * current;
-
- if ( ( &original_copy ) == this )
- return *this;
-
- Clear( _FILE_AND_LINE_ ); // Remove the current tree
-
- // 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.
- BinarySearchTree_size = 0;
-
- root = 0;
-
-
- // Copy the tree using a breadth first search
- // Put the children of the current node into the queue
- // Pop the queue, put its children into the queue, repeat until queue is empty
- if ( original_copy.BinarySearchTree_size == 0 )
- {
- BinarySearchTree_size = 0;
- }
-
- else
- {
- DataStructures::QueueLinkedList<node *> tree_queue;
-
- // Add the root of the tree I am copying from
- tree_queue.Push( original_copy.root );
-
- do
- {
- current = tree_queue.Pop();
-
- Add ( *( current->item ), _FILE_AND_LINE_ )
-
- ;
-
- // Add the child or children of the tree I am copying from to the queue
- if ( current->left != 0 )
- tree_queue.Push( current->left );
-
- if ( current->right != 0 )
- tree_queue.Push( current->right );
-
- }
-
- while ( tree_queue.Size() > 0 );
- }
-
- return *this;
- }
-
- template <class BinarySearchTreeType>
- inline void BinarySearchTree<BinarySearchTreeType>::Clear ( const char *file, unsigned int line )
- {
- typename BinarySearchTree::node * current, *parent;
-
- current = root;
-
- while ( BinarySearchTree_size > 0 )
- {
- if ( BinarySearchTree_size == 1 )
- {
- RakNet::OP_DELETE(root->item, file, line);
- RakNet::OP_DELETE(root, file, line);
- root = 0;
- BinarySearchTree_size = 0;
- }
-
- else
- {
- if ( current->left != 0 )
- {
- current = current->left;
- }
-
- else
- if ( current->right != 0 )
- {
- current = current->right;
- }
-
- else // leaf
- {
- // Not root node so must have a parent
- parent = FindParent( *( current->item ) );
-
- if ( ( parent->left ) == current )
- parent->left = 0;
- else
- parent->right = 0;
-
- RakNet::OP_DELETE(current->item, file, line);
-
- RakNet::OP_DELETE(current, file, line);
-
- current = parent;
-
- BinarySearchTree_size--;
- }
- }
- }
- }
-
- } // End namespace
- #endif
- #ifdef _MSC_VER
- #pragma warning( pop )
- #endif
|