DS_BinarySearchTree.h 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. /// \file DS_BinarySearchTree.h
  11. /// \internal
  12. /// \brief A binary search tree, and an AVL balanced BST derivation.
  13. ///
  14. #ifndef __BINARY_SEARCH_TREE_H
  15. #define __BINARY_SEARCH_TREE_H
  16. #include "DS_QueueLinkedList.h"
  17. #include "RakMemoryOverride.h"
  18. #include "Export.h"
  19. #ifdef _MSC_VER
  20. #pragma warning( push )
  21. #endif
  22. /// The namespace DataStructures was only added to avoid compiler errors for commonly named data structures
  23. /// As these data structures are stand-alone, you can use them outside of RakNet for your own projects if you wish.
  24. namespace DataStructures
  25. {
  26. /**
  27. * \brief A binary search tree and an AVL balanced binary search tree.
  28. * \details
  29. * Initilize with the following structure
  30. *
  31. * BinarySearchTree<TYPE>
  32. *
  33. * OR
  34. *
  35. * AVLBalancedBinarySearchTree<TYPE>
  36. *
  37. * Use the AVL balanced tree if you want the tree to be balanced after every deletion and addition. This avoids the potential
  38. * worst case scenario where ordered input to a binary search tree gives linear search time results. It's not needed
  39. * if input will be evenly distributed, in which case the search time is O (log n). The search time for the AVL
  40. * balanced binary tree is O (log n) irregardless of input.
  41. *
  42. * Has the following member functions
  43. * unsigned int Height(<index>) - Returns the height of the tree at the optional specified starting index. Default is the root
  44. * add(element) - adds an element to the BinarySearchTree
  45. * 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
  46. * bool IsInelement) - returns true if element is in the tree as defined by a comparison with the == operator. Otherwise returns false
  47. * DisplayInorder(array) - Fills an array with an inorder search of the elements in the tree. USER IS REPONSIBLE FOR ALLOCATING THE ARRAY!.
  48. * DisplayPreorder(array) - Fills an array with an preorder search of the elements in the tree. USER IS REPONSIBLE FOR ALLOCATING THE ARRAY!.
  49. * DisplayPostorder(array) - Fills an array with an postorder search of the elements in the tree. USER IS REPONSIBLE FOR ALLOCATING THE ARRAY!.
  50. * DisplayBreadthFirstSearch(array) - Fills an array with a breadth first search of the elements in the tree. USER IS REPONSIBLE FOR ALLOCATING THE ARRAY!.
  51. * clear - Destroys the tree. Same as calling the destructor
  52. * unsigned int Height() - Returns the height of the tree
  53. * unsigned int size() - returns the size of the BinarySearchTree
  54. * GetPointerToNode(element) - returns a pointer to the comparision element in the tree, allowing for direct modification when necessary with complex data types.
  55. * 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
  56. *
  57. *
  58. * EXAMPLE
  59. * @code
  60. * BinarySearchTree<int> A;
  61. * A.Add(10);
  62. * A.Add(15);
  63. * A.Add(5);
  64. * int* array = RakNet::OP_NEW<int >(A.Size(), _FILE_AND_LINE_ );
  65. * A.DisplayInorder(array);
  66. * array[0]; // returns 5
  67. * array[1]; // returns 10
  68. * array[2]; // returns 15
  69. * @endcode
  70. * compress - reallocates memory to fit the number of elements. Best used when the number of elements decreases
  71. *
  72. * clear - empties the BinarySearchTree and returns storage
  73. * The assignment and copy constructors are defined
  74. *
  75. * \note The template type must have the copy constructor and
  76. * assignment operator defined and must work with >, <, and == All
  77. * elements in the tree MUST be distinct The assignment operator is
  78. * defined between BinarySearchTree and AVLBalancedBinarySearchTree
  79. * as long as they are of the same template type. However, passing a
  80. * BinarySearchTree to an AVLBalancedBinarySearchTree will lose its
  81. * structure unless it happened to be AVL balanced to begin with
  82. * Requires queue_linked_list.cpp for the breadth first search used
  83. * in the copy constructor, overloaded assignment operator, and
  84. * display_breadth_first_search.
  85. *
  86. *
  87. */
  88. template <class BinarySearchTreeType>
  89. class RAK_DLL_EXPORT BinarySearchTree
  90. {
  91. public:
  92. struct node
  93. {
  94. BinarySearchTreeType* item;
  95. node* left;
  96. node* right;
  97. };
  98. BinarySearchTree();
  99. virtual ~BinarySearchTree();
  100. BinarySearchTree( const BinarySearchTree& original_type );
  101. BinarySearchTree& operator= ( const BinarySearchTree& original_copy );
  102. unsigned int Size( void );
  103. void Clear( const char *file, unsigned int line );
  104. unsigned int Height( node* starting_node = 0 );
  105. node* Add ( const BinarySearchTreeType& input, const char *file, unsigned int line );
  106. node* Del( const BinarySearchTreeType& input, const char *file, unsigned int line );
  107. bool IsIn( const BinarySearchTreeType& input );
  108. void DisplayInorder( BinarySearchTreeType* return_array );
  109. void DisplayPreorder( BinarySearchTreeType* return_array );
  110. void DisplayPostorder( BinarySearchTreeType* return_array );
  111. void DisplayBreadthFirstSearch( BinarySearchTreeType* return_array );
  112. BinarySearchTreeType*& GetPointerToNode( const BinarySearchTreeType& element );
  113. protected:
  114. node* root;
  115. enum Direction_Types
  116. {
  117. NOT_FOUND, LEFT, RIGHT, ROOT
  118. } direction;
  119. unsigned int HeightRecursive( node* current );
  120. unsigned int BinarySearchTree_size;
  121. node*& Find( const BinarySearchTreeType& element, node** parent );
  122. node*& FindParent( const BinarySearchTreeType& element );
  123. void DisplayPostorderRecursive( node* current, BinarySearchTreeType* return_array, unsigned int& index );
  124. void FixTree( node* current );
  125. };
  126. /// An AVLBalancedBinarySearchTree is a binary tree that is always balanced
  127. template <class BinarySearchTreeType>
  128. class RAK_DLL_EXPORT AVLBalancedBinarySearchTree : public BinarySearchTree<BinarySearchTreeType>
  129. {
  130. public:
  131. AVLBalancedBinarySearchTree() {}
  132. virtual ~AVLBalancedBinarySearchTree();
  133. void Add ( const BinarySearchTreeType& input );
  134. void Del( const BinarySearchTreeType& input );
  135. BinarySearchTree<BinarySearchTreeType>& operator= ( BinarySearchTree<BinarySearchTreeType>& original_copy )
  136. {
  137. return BinarySearchTree<BinarySearchTreeType>::operator= ( original_copy );
  138. }
  139. private:
  140. void BalanceTree( typename BinarySearchTree<BinarySearchTreeType>::node* current, bool rotateOnce );
  141. void RotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *C );
  142. void RotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node* C );
  143. void DoubleRotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *A );
  144. void DoubleRotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node* A );
  145. bool RightHigher( typename BinarySearchTree<BinarySearchTreeType>::node* A );
  146. bool LeftHigher( typename BinarySearchTree<BinarySearchTreeType>::node* A );
  147. };
  148. template <class BinarySearchTreeType>
  149. void AVLBalancedBinarySearchTree<BinarySearchTreeType>::BalanceTree( typename BinarySearchTree<BinarySearchTreeType>::node* current, bool rotateOnce )
  150. {
  151. int left_height, right_height;
  152. while ( current )
  153. {
  154. if ( current->left == 0 )
  155. left_height = 0;
  156. else
  157. left_height = Height( current->left );
  158. if ( current->right == 0 )
  159. right_height = 0;
  160. else
  161. right_height = Height( current->right );
  162. if ( right_height - left_height == 2 )
  163. {
  164. if ( RightHigher( current->right ) )
  165. RotateLeft( current->right );
  166. else
  167. DoubleRotateLeft( current );
  168. if ( rotateOnce )
  169. break;
  170. }
  171. else
  172. if ( right_height - left_height == -2 )
  173. {
  174. if ( LeftHigher( current->left ) )
  175. RotateRight( current->left );
  176. else
  177. DoubleRotateRight( current );
  178. if ( rotateOnce )
  179. break;
  180. }
  181. if ( current == this->root )
  182. break;
  183. current = FindParent( *( current->item ) );
  184. }
  185. }
  186. template <class BinarySearchTreeType>
  187. void AVLBalancedBinarySearchTree<BinarySearchTreeType>::Add ( const BinarySearchTreeType& input )
  188. {
  189. typename BinarySearchTree<BinarySearchTreeType>::node * current = BinarySearchTree<BinarySearchTreeType>::Add ( input, _FILE_AND_LINE_ );
  190. BalanceTree( current, true );
  191. }
  192. template <class BinarySearchTreeType>
  193. void AVLBalancedBinarySearchTree<BinarySearchTreeType>::Del( const BinarySearchTreeType& input )
  194. {
  195. typename BinarySearchTree<BinarySearchTreeType>::node * current = BinarySearchTree<BinarySearchTreeType>::Del( input, _FILE_AND_LINE_ );
  196. BalanceTree( current, false );
  197. }
  198. template <class BinarySearchTreeType>
  199. bool AVLBalancedBinarySearchTree<BinarySearchTreeType>::RightHigher( typename BinarySearchTree<BinarySearchTreeType>::node *A )
  200. {
  201. if ( A == 0 )
  202. return false;
  203. return Height( A->right ) > Height( A->left );
  204. }
  205. template <class BinarySearchTreeType>
  206. bool AVLBalancedBinarySearchTree<BinarySearchTreeType>::LeftHigher( typename BinarySearchTree<BinarySearchTreeType>::node *A )
  207. {
  208. if ( A == 0 )
  209. return false;
  210. return Height( A->left ) > Height( A->right );
  211. }
  212. template <class BinarySearchTreeType>
  213. void AVLBalancedBinarySearchTree<BinarySearchTreeType>::RotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *C )
  214. {
  215. typename BinarySearchTree<BinarySearchTreeType>::node * A, *B, *D;
  216. /*
  217. RIGHT ROTATION
  218. A = parent(b)
  219. b= parent(c)
  220. c = node to rotate around
  221. A
  222. | // Either direction
  223. B
  224. / \
  225. C
  226. / \
  227. D
  228. TO
  229. A
  230. | // Either Direction
  231. C
  232. / \
  233. B
  234. / \
  235. D
  236. <Leave all other branches branches AS-IS whether they point to another node or simply 0>
  237. */
  238. B = FindParent( *( C->item ) );
  239. A = FindParent( *( B->item ) );
  240. D = C->right;
  241. if ( A )
  242. {
  243. // Direction was set by the last find_parent call
  244. if ( this->direction == this->LEFT )
  245. A->left = C;
  246. else
  247. A->right = C;
  248. }
  249. else
  250. this->root = C; // If B has no parent parent then B must have been the root node
  251. B->left = D;
  252. C->right = B;
  253. }
  254. template <class BinarySearchTreeType>
  255. void AVLBalancedBinarySearchTree<BinarySearchTreeType>::DoubleRotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *A )
  256. {
  257. // 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.
  258. RotateLeft( A->left->right );
  259. RotateRight( A->left );
  260. }
  261. template <class BinarySearchTreeType>
  262. void AVLBalancedBinarySearchTree<BinarySearchTreeType>::RotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node *C )
  263. {
  264. typename BinarySearchTree<BinarySearchTreeType>::node * A, *B, *D;
  265. /*
  266. RIGHT ROTATION
  267. A = parent(b)
  268. b= parent(c)
  269. c = node to rotate around
  270. A
  271. | // Either direction
  272. B
  273. / \
  274. C
  275. / \
  276. D
  277. TO
  278. A
  279. | // Either Direction
  280. C
  281. / \
  282. B
  283. / \
  284. D
  285. <Leave all other branches branches AS-IS whether they point to another node or simply 0>
  286. */
  287. B = FindParent( *( C->item ) );
  288. A = FindParent( *( B->item ) );
  289. D = C->left;
  290. if ( A )
  291. {
  292. // Direction was set by the last find_parent call
  293. if ( this->direction == this->LEFT )
  294. A->left = C;
  295. else
  296. A->right = C;
  297. }
  298. else
  299. this->root = C; // If B has no parent parent then B must have been the root node
  300. B->right = D;
  301. C->left = B;
  302. }
  303. template <class BinarySearchTreeType>
  304. void AVLBalancedBinarySearchTree<BinarySearchTreeType>::DoubleRotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node *A )
  305. {
  306. // 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.
  307. RotateRight( A->right->left );
  308. RotateLeft( A->right );
  309. }
  310. template <class BinarySearchTreeType>
  311. AVLBalancedBinarySearchTree<BinarySearchTreeType>::~AVLBalancedBinarySearchTree()
  312. {
  313. this->Clear(_FILE_AND_LINE_);
  314. }
  315. template <class BinarySearchTreeType>
  316. unsigned int BinarySearchTree<BinarySearchTreeType>::Size( void )
  317. {
  318. return BinarySearchTree_size;
  319. }
  320. template <class BinarySearchTreeType>
  321. unsigned int BinarySearchTree<BinarySearchTreeType>::Height( typename BinarySearchTree::node* starting_node )
  322. {
  323. if ( BinarySearchTree_size == 0 || starting_node == 0 )
  324. return 0;
  325. else
  326. return HeightRecursive( starting_node );
  327. }
  328. // Recursively return the height of a binary tree
  329. template <class BinarySearchTreeType>
  330. unsigned int BinarySearchTree<BinarySearchTreeType>::HeightRecursive( typename BinarySearchTree::node* current )
  331. {
  332. unsigned int left_height = 0, right_height = 0;
  333. if ( ( current->left == 0 ) && ( current->right == 0 ) )
  334. return 1; // Leaf
  335. if ( current->left != 0 )
  336. left_height = 1 + HeightRecursive( current->left );
  337. if ( current->right != 0 )
  338. right_height = 1 + HeightRecursive( current->right );
  339. if ( left_height > right_height )
  340. return left_height;
  341. else
  342. return right_height;
  343. }
  344. template <class BinarySearchTreeType>
  345. BinarySearchTree<BinarySearchTreeType>::BinarySearchTree()
  346. {
  347. BinarySearchTree_size = 0;
  348. root = 0;
  349. }
  350. template <class BinarySearchTreeType>
  351. BinarySearchTree<BinarySearchTreeType>::~BinarySearchTree()
  352. {
  353. this->Clear(_FILE_AND_LINE_);
  354. }
  355. template <class BinarySearchTreeType>
  356. BinarySearchTreeType*& BinarySearchTree<BinarySearchTreeType>::GetPointerToNode( const BinarySearchTreeType& element )
  357. {
  358. static typename BinarySearchTree::node * tempnode;
  359. static BinarySearchTreeType* dummyptr = 0;
  360. tempnode = Find ( element, &tempnode );
  361. if ( this->direction == this->NOT_FOUND )
  362. return dummyptr;
  363. return tempnode->item;
  364. }
  365. template <class BinarySearchTreeType>
  366. typename BinarySearchTree<BinarySearchTreeType>::node*& BinarySearchTree<BinarySearchTreeType>::Find( const BinarySearchTreeType& element, typename BinarySearchTree<BinarySearchTreeType>::node** parent )
  367. {
  368. static typename BinarySearchTree::node * current;
  369. current = this->root;
  370. *parent = 0;
  371. this->direction = this->ROOT;
  372. if ( BinarySearchTree_size == 0 )
  373. {
  374. this->direction = this->NOT_FOUND;
  375. return current = 0;
  376. }
  377. // Check if the item is at the root
  378. if ( element == *( current->item ) )
  379. {
  380. this->direction = this->ROOT;
  381. return current;
  382. }
  383. #ifdef _MSC_VER
  384. #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
  385. #endif
  386. while ( true )
  387. {
  388. // Move pointer
  389. if ( element < *( current->item ) )
  390. {
  391. *parent = current;
  392. this->direction = this->LEFT;
  393. current = current->left;
  394. }
  395. else
  396. if ( element > *( current->item ) )
  397. {
  398. *parent = current;
  399. this->direction = this->RIGHT;
  400. current = current->right;
  401. }
  402. if ( current == 0 )
  403. break;
  404. // Check if new position holds the item
  405. if ( element == *( current->item ) )
  406. {
  407. return current;
  408. }
  409. }
  410. this->direction = this->NOT_FOUND;
  411. return current = 0;
  412. }
  413. template <class BinarySearchTreeType>
  414. typename BinarySearchTree<BinarySearchTreeType>::node*& BinarySearchTree<BinarySearchTreeType>::FindParent( const BinarySearchTreeType& element )
  415. {
  416. static typename BinarySearchTree::node * parent;
  417. Find ( element, &parent );
  418. return parent;
  419. }
  420. // Performs a series of value swaps starting with current to fix the tree if needed
  421. template <class BinarySearchTreeType>
  422. void BinarySearchTree<BinarySearchTreeType>::FixTree( typename BinarySearchTree::node* current )
  423. {
  424. BinarySearchTreeType temp;
  425. while ( 1 )
  426. {
  427. if ( ( ( current->left ) != 0 ) && ( *( current->item ) < *( current->left->item ) ) )
  428. {
  429. // Swap the current value with the one to the left
  430. temp = *( current->left->item );
  431. *( current->left->item ) = *( current->item );
  432. *( current->item ) = temp;
  433. current = current->left;
  434. }
  435. else
  436. if ( ( ( current->right ) != 0 ) && ( *( current->item ) > *( current->right->item ) ) )
  437. {
  438. // Swap the current value with the one to the right
  439. temp = *( current->right->item );
  440. *( current->right->item ) = *( current->item );
  441. *( current->item ) = temp;
  442. current = current->right;
  443. }
  444. else
  445. break; // current points to the right place so quit
  446. }
  447. }
  448. template <class BinarySearchTreeType>
  449. typename BinarySearchTree<BinarySearchTreeType>::node* BinarySearchTree<BinarySearchTreeType>::Del( const BinarySearchTreeType& input, const char *file, unsigned int line )
  450. {
  451. typename BinarySearchTree::node * node_to_delete, *current, *parent;
  452. if ( BinarySearchTree_size == 0 )
  453. return 0;
  454. if ( BinarySearchTree_size == 1 )
  455. {
  456. Clear(file, line);
  457. return 0;
  458. }
  459. node_to_delete = Find( input, &parent );
  460. if ( direction == NOT_FOUND )
  461. return 0; // Couldn't find the element
  462. current = node_to_delete;
  463. // Replace the deleted node with the appropriate value
  464. if ( ( current->right ) == 0 && ( current->left ) == 0 ) // Leaf node, just remove it
  465. {
  466. if ( parent )
  467. {
  468. if ( direction == LEFT )
  469. parent->left = 0;
  470. else
  471. parent->right = 0;
  472. }
  473. RakNet::OP_DELETE(node_to_delete->item, file, line);
  474. RakNet::OP_DELETE(node_to_delete, file, line);
  475. BinarySearchTree_size--;
  476. return parent;
  477. }
  478. else
  479. if ( ( current->right ) != 0 && ( current->left ) == 0 ) // Node has only one child, delete it and cause the parent to point to that child
  480. {
  481. if ( parent )
  482. {
  483. if ( direction == RIGHT )
  484. parent->right = current->right;
  485. else
  486. parent->left = current->right;
  487. }
  488. else
  489. root = current->right; // Without a parent this must be the root node
  490. RakNet::OP_DELETE(node_to_delete->item, file, line);
  491. RakNet::OP_DELETE(node_to_delete, file, line);
  492. BinarySearchTree_size--;
  493. return parent;
  494. }
  495. else
  496. if ( ( current->right ) == 0 && ( current->left ) != 0 ) // Node has only one child, delete it and cause the parent to point to that child
  497. {
  498. if ( parent )
  499. {
  500. if ( direction == RIGHT )
  501. parent->right = current->left;
  502. else
  503. parent->left = current->left;
  504. }
  505. else
  506. root = current->left; // Without a parent this must be the root node
  507. RakNet::OP_DELETE(node_to_delete->item, file, line);
  508. RakNet::OP_DELETE(node_to_delete, file, line);
  509. BinarySearchTree_size--;
  510. return parent;
  511. }
  512. else // Go right, then as left as far as you can
  513. {
  514. parent = current;
  515. direction = RIGHT;
  516. current = current->right; // Must have a right branch because the if statements above indicated that it has 2 branches
  517. while ( current->left )
  518. {
  519. direction = LEFT;
  520. parent = current;
  521. current = current->left;
  522. }
  523. // Replace the value held by the node to RakNet::OP_DELETE(with the value pointed to by current, _FILE_AND_LINE_);
  524. *( node_to_delete->item ) = *( current->item );
  525. // Delete current.
  526. // If it is a leaf node just delete it
  527. if ( current->right == 0 )
  528. {
  529. if ( direction == RIGHT )
  530. parent->right = 0;
  531. else
  532. parent->left = 0;
  533. RakNet::OP_DELETE(current->item, file, line);
  534. RakNet::OP_DELETE(current, file, line);
  535. BinarySearchTree_size--;
  536. return parent;
  537. }
  538. else
  539. {
  540. // Skip this node and make its parent point to its right branch
  541. if ( direction == RIGHT )
  542. parent->right = current->right;
  543. else
  544. parent->left = current->right;
  545. RakNet::OP_DELETE(current->item, file, line);
  546. RakNet::OP_DELETE(current, file, line);
  547. BinarySearchTree_size--;
  548. return parent;
  549. }
  550. }
  551. }
  552. template <class BinarySearchTreeType>
  553. typename BinarySearchTree<BinarySearchTreeType>::node* BinarySearchTree<BinarySearchTreeType>::Add ( const BinarySearchTreeType& input, const char *file, unsigned int line )
  554. {
  555. typename BinarySearchTree::node * current;
  556. // Add the new element to the tree according to the following alogrithm:
  557. // 1. If the current node is empty add the new leaf
  558. // 2. If the element is less than the current node then go down the left branch
  559. // 3. If the element is greater than the current node then go down the right branch
  560. if ( BinarySearchTree_size == 0 )
  561. {
  562. BinarySearchTree_size = 1;
  563. root = RakNet::OP_NEW<typename BinarySearchTree::node>( file, line );
  564. root->item = RakNet::OP_NEW<BinarySearchTreeType>( file, line );
  565. *( root->item ) = input;
  566. root->left = 0;
  567. root->right = 0;
  568. return root;
  569. }
  570. else
  571. {
  572. // start at the root
  573. current = root;
  574. #ifdef _MSC_VER
  575. #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
  576. #endif
  577. while ( true ) // This loop traverses the tree to find a spot for insertion
  578. {
  579. if ( input < *( current->item ) )
  580. {
  581. if ( current->left == 0 )
  582. {
  583. current->left = RakNet::OP_NEW<typename BinarySearchTree::node>( file, line );
  584. current->left->item = RakNet::OP_NEW<BinarySearchTreeType>( file, line );
  585. current = current->left;
  586. current->left = 0;
  587. current->right = 0;
  588. *( current->item ) = input;
  589. BinarySearchTree_size++;
  590. return current;
  591. }
  592. else
  593. {
  594. current = current->left;
  595. }
  596. }
  597. else
  598. if ( input > *( current->item ) )
  599. {
  600. if ( current->right == 0 )
  601. {
  602. current->right = RakNet::OP_NEW<typename BinarySearchTree::node>( file, line );
  603. current->right->item = RakNet::OP_NEW<BinarySearchTreeType>( file, line );
  604. current = current->right;
  605. current->left = 0;
  606. current->right = 0;
  607. *( current->item ) = input;
  608. BinarySearchTree_size++;
  609. return current;
  610. }
  611. else
  612. {
  613. current = current->right;
  614. }
  615. }
  616. else
  617. return 0; // ((input == current->item) == true) which is not allowed since the tree only takes discrete values. Do nothing
  618. }
  619. }
  620. }
  621. template <class BinarySearchTreeType>
  622. bool BinarySearchTree<BinarySearchTreeType>::IsIn( const BinarySearchTreeType& input )
  623. {
  624. typename BinarySearchTree::node * parent;
  625. find( input, &parent );
  626. if ( direction != NOT_FOUND )
  627. return true;
  628. else
  629. return false;
  630. }
  631. template <class BinarySearchTreeType>
  632. void BinarySearchTree<BinarySearchTreeType>::DisplayInorder( BinarySearchTreeType* return_array )
  633. {
  634. typename BinarySearchTree::node * current, *parent;
  635. bool just_printed = false;
  636. unsigned int index = 0;
  637. current = root;
  638. if ( BinarySearchTree_size == 0 )
  639. return ; // Do nothing for an empty tree
  640. else
  641. if ( BinarySearchTree_size == 1 )
  642. {
  643. return_array[ 0 ] = *( root->item );
  644. return ;
  645. }
  646. direction = ROOT; // Reset the direction
  647. while ( index != BinarySearchTree_size )
  648. {
  649. // 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
  650. if ( ( current->left != 0 ) && ( direction != LEFT ) && ( direction != RIGHT ) )
  651. {
  652. // Go left if the following 2 conditions are true
  653. // I can go left
  654. // I did not just move up from a right child
  655. // I did not just move up from a left child
  656. current = current->left;
  657. direction = ROOT; // Reset the direction
  658. }
  659. else
  660. if ( ( direction != RIGHT ) && ( just_printed == false ) )
  661. {
  662. // Otherwise, print the current node if the following 3 conditions are true:
  663. // I did not just move up from a right child
  664. // I did not print this ndoe last cycle
  665. return_array[ index++ ] = *( current->item );
  666. just_printed = true;
  667. }
  668. else
  669. if ( ( current->right != 0 ) && ( direction != RIGHT ) )
  670. {
  671. // Otherwise, go right if the following 2 conditions are true
  672. // I did not just move up from a right child
  673. // I can go right
  674. current = current->right;
  675. direction = ROOT; // Reset the direction
  676. just_printed = false;
  677. }
  678. else
  679. {
  680. // Otherwise I've done everything I can. Move up the tree one node
  681. parent = FindParent( *( current->item ) );
  682. current = parent;
  683. just_printed = false;
  684. }
  685. }
  686. }
  687. template <class BinarySearchTreeType>
  688. void BinarySearchTree<BinarySearchTreeType>::DisplayPreorder( BinarySearchTreeType* return_array )
  689. {
  690. typename BinarySearchTree::node * current, *parent;
  691. unsigned int index = 0;
  692. current = root;
  693. if ( BinarySearchTree_size == 0 )
  694. return ; // Do nothing for an empty tree
  695. else
  696. if ( BinarySearchTree_size == 1 )
  697. {
  698. return_array[ 0 ] = *( root->item );
  699. return ;
  700. }
  701. direction = ROOT; // Reset the direction
  702. return_array[ index++ ] = *( current->item );
  703. while ( index != BinarySearchTree_size )
  704. {
  705. // 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
  706. if ( ( current->left != 0 ) && ( direction != LEFT ) && ( direction != RIGHT ) )
  707. {
  708. current = current->left;
  709. direction = ROOT;
  710. // Everytime you move a node print it
  711. return_array[ index++ ] = *( current->item );
  712. }
  713. else
  714. if ( ( current->right != 0 ) && ( direction != RIGHT ) )
  715. {
  716. current = current->right;
  717. direction = ROOT;
  718. // Everytime you move a node print it
  719. return_array[ index++ ] = *( current->item );
  720. }
  721. else
  722. {
  723. // Otherwise I've done everything I can. Move up the tree one node
  724. parent = FindParent( *( current->item ) );
  725. current = parent;
  726. }
  727. }
  728. }
  729. template <class BinarySearchTreeType>
  730. inline void BinarySearchTree<BinarySearchTreeType>::DisplayPostorder( BinarySearchTreeType* return_array )
  731. {
  732. unsigned int index = 0;
  733. if ( BinarySearchTree_size == 0 )
  734. return ; // Do nothing for an empty tree
  735. else
  736. if ( BinarySearchTree_size == 1 )
  737. {
  738. return_array[ 0 ] = *( root->item );
  739. return ;
  740. }
  741. DisplayPostorderRecursive( root, return_array, index );
  742. }
  743. // Recursively do a postorder traversal
  744. template <class BinarySearchTreeType>
  745. void BinarySearchTree<BinarySearchTreeType>::DisplayPostorderRecursive( typename BinarySearchTree::node* current, BinarySearchTreeType* return_array, unsigned int& index )
  746. {
  747. if ( current->left != 0 )
  748. DisplayPostorderRecursive( current->left, return_array, index );
  749. if ( current->right != 0 )
  750. DisplayPostorderRecursive( current->right, return_array, index );
  751. return_array[ index++ ] = *( current->item );
  752. }
  753. template <class BinarySearchTreeType>
  754. void BinarySearchTree<BinarySearchTreeType>::DisplayBreadthFirstSearch( BinarySearchTreeType* return_array )
  755. {
  756. typename BinarySearchTree::node * current;
  757. unsigned int index = 0;
  758. // Display the tree using a breadth first search
  759. // Put the children of the current node into the queue
  760. // Pop the queue, put its children into the queue, repeat until queue is empty
  761. if ( BinarySearchTree_size == 0 )
  762. return ; // Do nothing for an empty tree
  763. else
  764. if ( BinarySearchTree_size == 1 )
  765. {
  766. return_array[ 0 ] = *( root->item );
  767. return ;
  768. }
  769. else
  770. {
  771. DataStructures::QueueLinkedList<node *> tree_queue;
  772. // Add the root of the tree I am copying from
  773. tree_queue.Push( root );
  774. do
  775. {
  776. current = tree_queue.Pop();
  777. return_array[ index++ ] = *( current->item );
  778. // Add the child or children of the tree I am copying from to the queue
  779. if ( current->left != 0 )
  780. tree_queue.Push( current->left );
  781. if ( current->right != 0 )
  782. tree_queue.Push( current->right );
  783. }
  784. while ( tree_queue.Size() > 0 );
  785. }
  786. }
  787. template <class BinarySearchTreeType>
  788. BinarySearchTree<BinarySearchTreeType>::BinarySearchTree( const BinarySearchTree& original_copy )
  789. {
  790. typename BinarySearchTree::node * current;
  791. // Copy the tree using a breadth first search
  792. // Put the children of the current node into the queue
  793. // Pop the queue, put its children into the queue, repeat until queue is empty
  794. // 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.
  795. BinarySearchTree_size = 0;
  796. root = 0;
  797. if ( original_copy.BinarySearchTree_size == 0 )
  798. {
  799. BinarySearchTree_size = 0;
  800. }
  801. else
  802. {
  803. DataStructures::QueueLinkedList<node *> tree_queue;
  804. // Add the root of the tree I am copying from
  805. tree_queue.Push( original_copy.root );
  806. do
  807. {
  808. current = tree_queue.Pop();
  809. Add ( *( current->item ), _FILE_AND_LINE_ )
  810. ;
  811. // Add the child or children of the tree I am copying from to the queue
  812. if ( current->left != 0 )
  813. tree_queue.Push( current->left );
  814. if ( current->right != 0 )
  815. tree_queue.Push( current->right );
  816. }
  817. while ( tree_queue.Size() > 0 );
  818. }
  819. }
  820. template <class BinarySearchTreeType>
  821. BinarySearchTree<BinarySearchTreeType>& BinarySearchTree<BinarySearchTreeType>::operator= ( const BinarySearchTree& original_copy )
  822. {
  823. typename BinarySearchTree::node * current;
  824. if ( ( &original_copy ) == this )
  825. return *this;
  826. Clear( _FILE_AND_LINE_ ); // Remove the current tree
  827. // 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.
  828. BinarySearchTree_size = 0;
  829. root = 0;
  830. // Copy the tree using a breadth first search
  831. // Put the children of the current node into the queue
  832. // Pop the queue, put its children into the queue, repeat until queue is empty
  833. if ( original_copy.BinarySearchTree_size == 0 )
  834. {
  835. BinarySearchTree_size = 0;
  836. }
  837. else
  838. {
  839. DataStructures::QueueLinkedList<node *> tree_queue;
  840. // Add the root of the tree I am copying from
  841. tree_queue.Push( original_copy.root );
  842. do
  843. {
  844. current = tree_queue.Pop();
  845. Add ( *( current->item ), _FILE_AND_LINE_ )
  846. ;
  847. // Add the child or children of the tree I am copying from to the queue
  848. if ( current->left != 0 )
  849. tree_queue.Push( current->left );
  850. if ( current->right != 0 )
  851. tree_queue.Push( current->right );
  852. }
  853. while ( tree_queue.Size() > 0 );
  854. }
  855. return *this;
  856. }
  857. template <class BinarySearchTreeType>
  858. inline void BinarySearchTree<BinarySearchTreeType>::Clear ( const char *file, unsigned int line )
  859. {
  860. typename BinarySearchTree::node * current, *parent;
  861. current = root;
  862. while ( BinarySearchTree_size > 0 )
  863. {
  864. if ( BinarySearchTree_size == 1 )
  865. {
  866. RakNet::OP_DELETE(root->item, file, line);
  867. RakNet::OP_DELETE(root, file, line);
  868. root = 0;
  869. BinarySearchTree_size = 0;
  870. }
  871. else
  872. {
  873. if ( current->left != 0 )
  874. {
  875. current = current->left;
  876. }
  877. else
  878. if ( current->right != 0 )
  879. {
  880. current = current->right;
  881. }
  882. else // leaf
  883. {
  884. // Not root node so must have a parent
  885. parent = FindParent( *( current->item ) );
  886. if ( ( parent->left ) == current )
  887. parent->left = 0;
  888. else
  889. parent->right = 0;
  890. RakNet::OP_DELETE(current->item, file, line);
  891. RakNet::OP_DELETE(current, file, line);
  892. current = parent;
  893. BinarySearchTree_size--;
  894. }
  895. }
  896. }
  897. }
  898. } // End namespace
  899. #endif
  900. #ifdef _MSC_VER
  901. #pragma warning( pop )
  902. #endif
粤ICP备19079148号