![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
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.