SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DS_BinarySearchTree.h
Go to the documentation of this file.
1 /*
2 * Original work: 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 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2017, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
20
21
22 #ifndef __BINARY_SEARCH_TREE_H
23 #define __BINARY_SEARCH_TREE_H
24
25 #include "DS_QueueLinkedList.h"
26 #include "memoryoverride.h"
27 #include "Export.h"
28
29
32 namespace DataStructures
33 {
96 template <class BinarySearchTreeType>
97 class RAK_DLL_EXPORT BinarySearchTree
98 {
99
100 public:
101
102 struct node
103 {
104 BinarySearchTreeType* item;
105 node* left;
106 node* right;
107 };
108
109 BinarySearchTree();
110 virtual ~BinarySearchTree();
111 BinarySearchTree( const BinarySearchTree& original_type );
112 BinarySearchTree& operator= ( const BinarySearchTree& original_copy );
113 unsigned int Size( void );
114 void Clear( const char *file, unsigned int line );
115 unsigned int Height( node* starting_node = 0 );
116 node* Add ( const BinarySearchTreeType& input, const char *file, unsigned int line );
117 node* Del( const BinarySearchTreeType& input, const char *file, unsigned int line );
118 bool IsIn( const BinarySearchTreeType& input );
119 void DisplayInorder( BinarySearchTreeType* return_array );
120 void DisplayPreorder( BinarySearchTreeType* return_array );
121 void DisplayPostorder( BinarySearchTreeType* return_array );
122 void DisplayBreadthFirstSearch( BinarySearchTreeType* return_array );
123 BinarySearchTreeType*& GetPointerToNode( const BinarySearchTreeType& element );
124
125 protected:
126
127 node* root;
128
129 enum Direction_Types
130 {
131 NOT_FOUND, LEFT, RIGHT, ROOT
132 } direction;
133 unsigned int HeightRecursive( node* current );
134 unsigned int BinarySearchTree_size;
135 node*& Find( const BinarySearchTreeType& element, node** parent );
136 node*& FindParent( const BinarySearchTreeType& element );
137 void DisplayPostorderRecursive( node* current, BinarySearchTreeType* return_array, unsigned int& index );
138 void FixTree( node* current );
139
140 };
141
143 template <class BinarySearchTreeType>
144 class RAK_DLL_EXPORT AVLBalancedBinarySearchTree : public BinarySearchTree<BinarySearchTreeType>
145 {
146
147 public:
148 AVLBalancedBinarySearchTree() {}
149 virtual ~AVLBalancedBinarySearchTree();
150 void Add ( const BinarySearchTreeType& input );
151 void Del( const BinarySearchTreeType& input );
152 BinarySearchTree<BinarySearchTreeType>& operator= ( BinarySearchTree<BinarySearchTreeType>& original_copy )
153 {
154 return BinarySearchTree<BinarySearchTreeType>::operator= ( original_copy );
155 }
156
157 private:
158 void BalanceTree( typename BinarySearchTree<BinarySearchTreeType>::node* current, bool rotateOnce );
159 void RotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *C );
160 void RotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node* C );
161 void DoubleRotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *A );
162 void DoubleRotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node* A );
163 bool RightHigher( typename BinarySearchTree<BinarySearchTreeType>::node* A );
164 bool LeftHigher( typename BinarySearchTree<BinarySearchTreeType>::node* A );
165 };
166
167 template <class BinarySearchTreeType>
168 void AVLBalancedBinarySearchTree<BinarySearchTreeType>::BalanceTree( typename BinarySearchTree<BinarySearchTreeType>::node* current, bool rotateOnce )
169 {
170 int left_height, right_height;
171
172 while ( current )
173 {
174 if ( current->left == 0 )
175 left_height = 0;
176 else
177 left_height = Height( current->left );
178
179 if ( current->right == 0 )
180 right_height = 0;
181 else
182 right_height = Height( current->right );
183
184 if ( right_height - left_height == 2 )
185 {
186 if ( RightHigher( current->right ) )
187 RotateLeft( current->right );
188 else
189 DoubleRotateLeft( current );
190
191 if ( rotateOnce )
192 break;
193 }
194
195 else
196 if ( right_height - left_height == -2 )
197 {
198 if ( LeftHigher( current->left ) )
199 RotateRight( current->left );
200 else
201 DoubleRotateRight( current );
202
203 if ( rotateOnce )
204 break;
205 }
206
207 if ( current == this->root )
208 break;
209
210 current = FindParent( *( current->item ) );
211
212 }
213 }
214
215 template <class BinarySearchTreeType>
216 void AVLBalancedBinarySearchTree<BinarySearchTreeType>::Add ( const BinarySearchTreeType& input )
217 {
218
219 typename BinarySearchTree<BinarySearchTreeType>::node * current = BinarySearchTree<BinarySearchTreeType>::Add ( input, _FILE_AND_LINE_ );
220 BalanceTree( current, true );
221 }
222
223 template <class BinarySearchTreeType>
224 void AVLBalancedBinarySearchTree<BinarySearchTreeType>::Del( const BinarySearchTreeType& input )
225 {
226 typename BinarySearchTree<BinarySearchTreeType>::node * current = BinarySearchTree<BinarySearchTreeType>::Del( input, _FILE_AND_LINE_ );
227 BalanceTree( current, false );
228
229 }
230
231 template <class BinarySearchTreeType>
232 bool AVLBalancedBinarySearchTree<BinarySearchTreeType>::RightHigher( typename BinarySearchTree<BinarySearchTreeType>::node *A )
233 {
234 if ( A == 0 )
235 return false;
236
237 return Height( A->right ) > Height( A->left );
238 }
239
240 template <class BinarySearchTreeType>
241 bool AVLBalancedBinarySearchTree<BinarySearchTreeType>::LeftHigher( typename BinarySearchTree<BinarySearchTreeType>::node *A )
242 {
243 if ( A == 0 )
244 return false;
245
246 return Height( A->left ) > Height( A->right );
247 }
248
249 template <class BinarySearchTreeType>
250 void AVLBalancedBinarySearchTree<BinarySearchTreeType>::RotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *C )
251 {
252 typename BinarySearchTree<BinarySearchTreeType>::node * A, *B, *D;
253 /*
254 RIGHT ROTATION
255
256 A = parent(b)
257 b= parent(c)
258 c = node to rotate around
259
260 A
261 | // Either direction
262 B
263 / \
264 C
265 / \
266 D
267
268 TO
269
270 A
271 | // Either Direction
272 C
273 / \
274 B
275 / \
276 D
277
278
279 <Leave all other branches branches AS-IS whether they point to another node or simply 0>
280
281 */
282
283 B = FindParent( *( C->item ) );
284 A = FindParent( *( B->item ) );
285 D = C->right;
286
287 if ( A )
288 {
289 // Direction was set by the last find_parent call
290
291 if ( this->direction == this->LEFT )
292 A->left = C;
293 else
294 A->right = C;
295 }
296
297 else
298 this->root = C; // If B has no parent parent then B must have been the root node
299
300 B->left = D;
301
302 C->right = B;
303 }
304
305 template <class BinarySearchTreeType>
306 void AVLBalancedBinarySearchTree<BinarySearchTreeType>::DoubleRotateRight( typename BinarySearchTree<BinarySearchTreeType>::node *A )
307 {
308 // 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.
309 RotateLeft( A->left->right );
310 RotateRight( A->left );
311 }
312
313 template <class BinarySearchTreeType>
314 void AVLBalancedBinarySearchTree<BinarySearchTreeType>::RotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node *C )
315 {
316 typename BinarySearchTree<BinarySearchTreeType>::node * A, *B, *D;
317 /*
318 RIGHT ROTATION
319
320 A = parent(b)
321 b= parent(c)
322 c = node to rotate around
323
324 A
325 | // Either direction
326 B
327 / \
328 C
329 / \
330 D
331
332 TO
333
334 A
335 | // Either Direction
336 C
337 / \
338 B
339 / \
340 D
341
342
343 <Leave all other branches branches AS-IS whether they point to another node or simply 0>
344
345 */
346
347 B = FindParent( *( C->item ) );
348 A = FindParent( *( B->item ) );
349 D = C->left;
350
351 if ( A )
352 {
353 // Direction was set by the last find_parent call
354
355 if ( this->direction == this->LEFT )
356 A->left = C;
357 else
358 A->right = C;
359 }
360
361 else
362 this->root = C; // If B has no parent parent then B must have been the root node
363
364 B->right = D;
365
366 C->left = B;
367 }
368
369 template <class BinarySearchTreeType>
370 void AVLBalancedBinarySearchTree<BinarySearchTreeType>::DoubleRotateLeft( typename BinarySearchTree<BinarySearchTreeType>::node *A )
371 {
372 // 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.
373 RotateRight( A->right->left );
374 RotateLeft( A->right );
375 }
376
377 template <class BinarySearchTreeType>
378 AVLBalancedBinarySearchTree<BinarySearchTreeType>::~AVLBalancedBinarySearchTree()
379 {
380 this->Clear(_FILE_AND_LINE_);
381 }
382
383 template <class BinarySearchTreeType>
384 unsigned int BinarySearchTree<BinarySearchTreeType>::Size( void )
385 {
386 return BinarySearchTree_size;
387 }
388
389 template <class BinarySearchTreeType>
390 unsigned int BinarySearchTree<BinarySearchTreeType>::Height( typename BinarySearchTree::node* starting_node )
391 {
392 if ( BinarySearchTree_size == 0 || starting_node == 0 )
393 return 0;
394 else
395 return HeightRecursive( starting_node );
396 }
397
398 // Recursively return the height of a binary tree
399 template <class BinarySearchTreeType>
400 unsigned int BinarySearchTree<BinarySearchTreeType>::HeightRecursive( typename BinarySearchTree::node* current )
401 {
402 unsigned int left_height = 0, right_height = 0;
403
404 if ( ( current->left == 0 ) && ( current->right == 0 ) )
405 return 1; // Leaf
406
407 if ( current->left != 0 )
408 left_height = 1 + HeightRecursive( current->left );
409
410 if ( current->right != 0 )
411 right_height = 1 + HeightRecursive( current->right );
412
413 if ( left_height > right_height )
414 return left_height;
415 else
416 return right_height;
417 }
418
419 template <class BinarySearchTreeType>
420 BinarySearchTree<BinarySearchTreeType>::BinarySearchTree()
421 {
422 BinarySearchTree_size = 0;
423 root = 0;
424 }
425
426 template <class BinarySearchTreeType>
427 BinarySearchTree<BinarySearchTreeType>::~BinarySearchTree()
428 {
429 this->Clear(_FILE_AND_LINE_);
430 }
431
432 template <class BinarySearchTreeType>
433 BinarySearchTreeType*& BinarySearchTree<BinarySearchTreeType>::GetPointerToNode( const BinarySearchTreeType& element )
434 {
435 static typename BinarySearchTree::node * tempnode;
436 static BinarySearchTreeType* dummyptr = 0;
437 tempnode = Find ( element, &tempnode );
438
439 if ( this->direction == this->NOT_FOUND )
440 return dummyptr;
441
442 return tempnode->item;
443 }
444
445 template <class BinarySearchTreeType>
446 typename BinarySearchTree<BinarySearchTreeType>::node*& BinarySearchTree<BinarySearchTreeType>::Find( const BinarySearchTreeType& element, typename BinarySearchTree<BinarySearchTreeType>::node** parent )
447 {
448 static typename BinarySearchTree::node * current;
449
450 current = this->root;
451 *parent = 0;
452 this->direction = this->ROOT;
453
454 if ( BinarySearchTree_size == 0 )
455 {
456 this->direction = this->NOT_FOUND;
457 return current = 0;
458 }
459
460 // Check if the item is at the root
461 if ( element == *( current->item ) )
462 {
463 this->direction = this->ROOT;
464 return current;
465 }
466
467 for (;;)
468 {
469 // Move pointer
470
471 if ( element < *( current->item ) )
472 {
473 *parent = current;
474 this->direction = this->LEFT;
475 current = current->left;
476 }
477
478 else
479 if ( element > *( current->item ) )
480 {
481 *parent = current;
482 this->direction = this->RIGHT;
483 current = current->right;
484 }
485
486 if ( current == 0 )
487 break;
488
489 // Check if new position holds the item
490 if ( element == *( current->item ) )
491 {
492 return current;
493 }
494 }
495
496
497 this->direction = this->NOT_FOUND;
498 return current = 0;
499 }
500
501 template <class BinarySearchTreeType>
502 typename BinarySearchTree<BinarySearchTreeType>::node*& BinarySearchTree<BinarySearchTreeType>::FindParent( const BinarySearchTreeType& element )
503 {
504 static typename BinarySearchTree::node * parent;
505 Find ( element, &parent );
506 return parent;
507 }
508
509 // Performs a series of value swaps starting with current to fix the tree if needed
510 template <class BinarySearchTreeType>
511 void BinarySearchTree<BinarySearchTreeType>::FixTree( typename BinarySearchTree::node* current )
512 {
513 BinarySearchTreeType temp;
514
515 while ( 1 )
516 {
517 if ( ( ( current->left ) != 0 ) && ( *( current->item ) < *( current->left->item ) ) )
518 {
519 // Swap the current value with the one to the left
520 temp = *( current->left->item );
521 *( current->left->item ) = *( current->item );
522 *( current->item ) = temp;
523 current = current->left;
524 }
525
526 else
527 if ( ( ( current->right ) != 0 ) && ( *( current->item ) > *( current->right->item ) ) )
528 {
529 // Swap the current value with the one to the right
530 temp = *( current->right->item );
531 *( current->right->item ) = *( current->item );
532 *( current->item ) = temp;
533 current = current->right;
534 }
535
536 else
537 break; // current points to the right place so quit
538 }
539 }
540
541 template <class BinarySearchTreeType>
542 typename BinarySearchTree<BinarySearchTreeType>::node* BinarySearchTree<BinarySearchTreeType>::Del( const BinarySearchTreeType& input, const char *file, unsigned int line )
543 {
544 typename BinarySearchTree::node * node_to_delete, *current, *parent;
545
546 if ( BinarySearchTree_size == 0 )
547 return 0;
548
549 if ( BinarySearchTree_size == 1 )
550 {
551 Clear(file, line);
552 return 0;
553 }
554
555 node_to_delete = Find( input, &parent );
556
557 if ( direction == NOT_FOUND )
558 return 0; // Couldn't find the element
559
560 current = node_to_delete;
561
562 // Replace the deleted node with the appropriate value
563 if ( ( current->right ) == 0 && ( current->left ) == 0 ) // Leaf node, just remove it
564 {
565
566 if ( parent )
567 {
568 if ( direction == LEFT )
569 parent->left = 0;
570 else
571 parent->right = 0;
572 }
573
574 SLNet::OP_DELETE(node_to_delete->item, file, line);
575 SLNet::OP_DELETE(node_to_delete, file, line);
576 BinarySearchTree_size--;
577 return parent;
578 }
579 else
580 if ( ( current->right ) != 0 && ( current->left ) == 0 ) // Node has only one child, delete it and cause the parent to point to that child
581 {
582
583 if ( parent )
584 {
585 if ( direction == RIGHT )
586 parent->right = current->right;
587 else
588 parent->left = current->right;
589 }
590
591 else
592 root = current->right; // Without a parent this must be the root node
593
594 SLNet::OP_DELETE(node_to_delete->item, file, line);
595
596 SLNet::OP_DELETE(node_to_delete, file, line);
597
598 BinarySearchTree_size--;
599
600 return parent;
601 }
602 else
603 if ( ( current->right ) == 0 && ( current->left ) != 0 ) // Node has only one child, delete it and cause the parent to point to that child
604 {
605
606 if ( parent )
607 {
608 if ( direction == RIGHT )
609 parent->right = current->left;
610 else
611 parent->left = current->left;
612 }
613
614 else
615 root = current->left; // Without a parent this must be the root node
616
617 SLNet::OP_DELETE(node_to_delete->item, file, line);
618
619 SLNet::OP_DELETE(node_to_delete, file, line);
620
621 BinarySearchTree_size--;
622
623 return parent;
624 }
625 else // Go right, then as left as far as you can
626 {
627 parent = current;
628 direction = RIGHT;
629 current = current->right; // Must have a right branch because the if statements above indicated that it has 2 branches
630
631 while ( current->left )
632 {
633 direction = LEFT;
634 parent = current;
635 current = current->left;
636 }
637
638 // Replace the value held by the node to SLNet::OP_DELETE(with the value pointed to by current, _FILE_AND_LINE_);
639 *( node_to_delete->item ) = *( current->item );
640
641 // Delete current.
642 // If it is a leaf node just delete it
643 if ( current->right == 0 )
644 {
645 if ( direction == RIGHT )
646 parent->right = 0;
647 else
648 parent->left = 0;
649
650 SLNet::OP_DELETE(current->item, file, line);
651
652 SLNet::OP_DELETE(current, file, line);
653
654 BinarySearchTree_size--;
655
656 return parent;
657 }
658
659 else
660 {
661 // Skip this node and make its parent point to its right branch
662
663 if ( direction == RIGHT )
664 parent->right = current->right;
665 else
666 parent->left = current->right;
667
668 SLNet::OP_DELETE(current->item, file, line);
669
670 SLNet::OP_DELETE(current, file, line);
671
672 BinarySearchTree_size--;
673
674 return parent;
675 }
676 }
677 }
678
679 template <class BinarySearchTreeType>
680 typename BinarySearchTree<BinarySearchTreeType>::node* BinarySearchTree<BinarySearchTreeType>::Add ( const BinarySearchTreeType& input, const char *file, unsigned int line )
681 {
682 typename BinarySearchTree::node * current;
683
684 // Add the new element to the tree according to the following alogrithm:
685 // 1. If the current node is empty add the new leaf
686 // 2. If the element is less than the current node then go down the left branch
687 // 3. If the element is greater than the current node then go down the right branch
688
689 if ( BinarySearchTree_size == 0 )
690 {
691 BinarySearchTree_size = 1;
692 root = SLNet::OP_NEW<typename BinarySearchTree::node>( file, line );
693 root->item = SLNet::OP_NEW<BinarySearchTreeType>( file, line );
694 *( root->item ) = input;
695 root->left = 0;
696 root->right = 0;
697
698 return root;
699 }
700
701 else
702 {
703 // start at the root
704 current = root;
705
706 for(;;) // This loop traverses the tree to find a spot for insertion
707 {
708
709 if ( input < *( current->item ) )
710 {
711 if ( current->left == 0 )
712 {
713 current->left = SLNet::OP_NEW<typename BinarySearchTree::node>( file, line );
714 current->left->item = SLNet::OP_NEW<BinarySearchTreeType>( file, line );
715 current = current->left;
716 current->left = 0;
717 current->right = 0;
718 *( current->item ) = input;
719
720 BinarySearchTree_size++;
721 return current;
722 }
723
724 else
725 {
726 current = current->left;
727 }
728 }
729
730 else
731 if ( input > *( current->item ) )
732 {
733 if ( current->right == 0 )
734 {
735 current->right = SLNet::OP_NEW<typename BinarySearchTree::node>( file, line );
736 current->right->item = SLNet::OP_NEW<BinarySearchTreeType>( file, line );
737 current = current->right;
738 current->left = 0;
739 current->right = 0;
740 *( current->item ) = input;
741
742 BinarySearchTree_size++;
743 return current;
744 }
745
746 else
747 {
748 current = current->right;
749 }
750 }
751
752 else
753 return 0; // ((input == current->item) == true) which is not allowed since the tree only takes discrete values. Do nothing
754 }
755 }
756 }
757
758 template <class BinarySearchTreeType>
759 bool BinarySearchTree<BinarySearchTreeType>::IsIn( const BinarySearchTreeType& input )
760 {
761 typename BinarySearchTree::node * parent;
762 find( input, &parent );
763
764 if ( direction != NOT_FOUND )
765 return true;
766 else
767 return false;
768 }
769
770
771 template <class BinarySearchTreeType>
772 void BinarySearchTree<BinarySearchTreeType>::DisplayInorder( BinarySearchTreeType* return_array )
773 {
774 typename BinarySearchTree::node * current, *parent;
775 bool just_printed = false;
776
777 unsigned int index = 0;
778
779 current = root;
780
781 if ( BinarySearchTree_size == 0 )
782 return ; // Do nothing for an empty tree
783
784 else
785 if ( BinarySearchTree_size == 1 )
786 {
787 return_array[ 0 ] = *( root->item );
788 return ;
789 }
790
791
792 direction = ROOT; // Reset the direction
793
794 while ( index != BinarySearchTree_size )
795 {
796 // 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
797
798 if ( ( current->left != 0 ) && ( direction != LEFT ) && ( direction != RIGHT ) )
799 {
800 // Go left if the following 2 conditions are true
801 // I can go left
802 // I did not just move up from a right child
803 // I did not just move up from a left child
804
805 current = current->left;
806 direction = ROOT; // Reset the direction
807 }
808
809 else
810 if ( ( direction != RIGHT ) && ( just_printed == false ) )
811 {
812 // Otherwise, print the current node if the following 3 conditions are true:
813 // I did not just move up from a right child
814 // I did not print this ndoe last cycle
815
816 return_array[ index++ ] = *( current->item );
817 just_printed = true;
818 }
819
820 else
821 if ( ( current->right != 0 ) && ( direction != RIGHT ) )
822 {
823 // Otherwise, go right if the following 2 conditions are true
824 // I did not just move up from a right child
825 // I can go right
826
827 current = current->right;
828 direction = ROOT; // Reset the direction
829 just_printed = false;
830 }
831
832 else
833 {
834 // Otherwise I've done everything I can. Move up the tree one node
835 parent = FindParent( *( current->item ) );
836 current = parent;
837 just_printed = false;
838 }
839 }
840 }
841
842 template <class BinarySearchTreeType>
843 void BinarySearchTree<BinarySearchTreeType>::DisplayPreorder( BinarySearchTreeType* return_array )
844 {
845 typename BinarySearchTree::node * current, *parent;
846
847 unsigned int index = 0;
848
849 current = root;
850
851 if ( BinarySearchTree_size == 0 )
852 return ; // Do nothing for an empty tree
853
854 else
855 if ( BinarySearchTree_size == 1 )
856 {
857 return_array[ 0 ] = *( root->item );
858 return ;
859 }
860
861
862 direction = ROOT; // Reset the direction
863 return_array[ index++ ] = *( current->item );
864
865 while ( index != BinarySearchTree_size )
866 {
867 // 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
868
869 if ( ( current->left != 0 ) && ( direction != LEFT ) && ( direction != RIGHT ) )
870 {
871
872 current = current->left;
873 direction = ROOT;
874
875 // Everytime you move a node print it
876 return_array[ index++ ] = *( current->item );
877 }
878
879 else
880 if ( ( current->right != 0 ) && ( direction != RIGHT ) )
881 {
882 current = current->right;
883 direction = ROOT;
884
885 // Everytime you move a node print it
886 return_array[ index++ ] = *( current->item );
887 }
888
889 else
890 {
891 // Otherwise I've done everything I can. Move up the tree one node
892 parent = FindParent( *( current->item ) );
893 current = parent;
894 }
895 }
896 }
897
898 template <class BinarySearchTreeType>
899 inline void BinarySearchTree<BinarySearchTreeType>::DisplayPostorder( BinarySearchTreeType* return_array )
900 {
901 unsigned int index = 0;
902
903 if ( BinarySearchTree_size == 0 )
904 return ; // Do nothing for an empty tree
905
906 else
907 if ( BinarySearchTree_size == 1 )
908 {
909 return_array[ 0 ] = *( root->item );
910 return ;
911 }
912
913 DisplayPostorderRecursive( root, return_array, index );
914 }
915
916
917 // Recursively do a postorder traversal
918 template <class BinarySearchTreeType>
919 void BinarySearchTree<BinarySearchTreeType>::DisplayPostorderRecursive( typename BinarySearchTree::node* current, BinarySearchTreeType* return_array, unsigned int& index )
920 {
921 if ( current->left != 0 )
922 DisplayPostorderRecursive( current->left, return_array, index );
923
924 if ( current->right != 0 )
925 DisplayPostorderRecursive( current->right, return_array, index );
926
927 return_array[ index++ ] = *( current->item );
928
929 }
930
931
932 template <class BinarySearchTreeType>
933 void BinarySearchTree<BinarySearchTreeType>::DisplayBreadthFirstSearch( BinarySearchTreeType* return_array )
934 {
935 typename BinarySearchTree::node * current;
936 unsigned int index = 0;
937
938 // Display the tree using a breadth first search
939 // Put the children of the current node into the queue
940 // Pop the queue, put its children into the queue, repeat until queue is empty
941
942 if ( BinarySearchTree_size == 0 )
943 return ; // Do nothing for an empty tree
944
945 else
946 if ( BinarySearchTree_size == 1 )
947 {
948 return_array[ 0 ] = *( root->item );
949 return ;
950 }
951
952 else
953 {
954 DataStructures::QueueLinkedList<node *> tree_queue;
955
956 // Add the root of the tree I am copying from
957 tree_queue.Push( root );
958
959 do
960 {
961 current = tree_queue.Pop();
962 return_array[ index++ ] = *( current->item );
963
964 // Add the child or children of the tree I am copying from to the queue
965
966 if ( current->left != 0 )
967 tree_queue.Push( current->left );
968
969 if ( current->right != 0 )
970 tree_queue.Push( current->right );
971
972 }
973
974 while ( tree_queue.Size() > 0 );
975 }
976 }
977
978
979 template <class BinarySearchTreeType>
980 BinarySearchTree<BinarySearchTreeType>::BinarySearchTree( const BinarySearchTree& original_copy )
981 {
982 typename BinarySearchTree::node * current;
983 // Copy the tree using a breadth first search
984 // Put the children of the current node into the queue
985 // Pop the queue, put its children into the queue, repeat until queue is empty
986
987 // 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.
988 BinarySearchTree_size = 0;
989 root = 0;
990
991 if ( original_copy.BinarySearchTree_size == 0 )
992 {
993 BinarySearchTree_size = 0;
994 }
995
996 else
997 {
998 DataStructures::QueueLinkedList<node *> tree_queue;
999
1000 // Add the root of the tree I am copying from
1001 tree_queue.Push( original_copy.root );
1002
1003 do
1004 {
1005 current = tree_queue.Pop();
1006
1007 Add ( *( current->item ), _FILE_AND_LINE_ )
1008
1009 ;
1010
1011 // Add the child or children of the tree I am copying from to the queue
1012 if ( current->left != 0 )
1013 tree_queue.Push( current->left );
1014
1015 if ( current->right != 0 )
1016 tree_queue.Push( current->right );
1017
1018 }
1019
1020 while ( tree_queue.Size() > 0 );
1021 }
1022 }
1023
1024 template <class BinarySearchTreeType>
1025 BinarySearchTree<BinarySearchTreeType>& BinarySearchTree<BinarySearchTreeType>::operator= ( const BinarySearchTree& original_copy )
1026 {
1027 typename BinarySearchTree::node * current;
1028
1029 if ( ( &original_copy ) == this )
1030 return *this;
1031
1032 Clear( _FILE_AND_LINE_ ); // Remove the current tree
1033
1034 // 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.
1035 BinarySearchTree_size = 0;
1036
1037 root = 0;
1038
1039
1040 // Copy the tree using a breadth first search
1041 // Put the children of the current node into the queue
1042 // Pop the queue, put its children into the queue, repeat until queue is empty
1043 if ( original_copy.BinarySearchTree_size == 0 )
1044 {
1045 BinarySearchTree_size = 0;
1046 }
1047
1048 else
1049 {
1050 DataStructures::QueueLinkedList<node *> tree_queue;
1051
1052 // Add the root of the tree I am copying from
1053 tree_queue.Push( original_copy.root );
1054
1055 do
1056 {
1057 current = tree_queue.Pop();
1058
1059 Add ( *( current->item ), _FILE_AND_LINE_ )
1060
1061 ;
1062
1063 // Add the child or children of the tree I am copying from to the queue
1064 if ( current->left != 0 )
1065 tree_queue.Push( current->left );
1066
1067 if ( current->right != 0 )
1068 tree_queue.Push( current->right );
1069
1070 }
1071
1072 while ( tree_queue.Size() > 0 );
1073 }
1074
1075 return *this;
1076 }
1077
1078 template <class BinarySearchTreeType>
1079 inline void BinarySearchTree<BinarySearchTreeType>::Clear ( const char *file, unsigned int line )
1080 {
1081 typename BinarySearchTree::node * current, *parent;
1082
1083 current = root;
1084
1085 while ( BinarySearchTree_size > 0 )
1086 {
1087 if ( BinarySearchTree_size == 1 )
1088 {
1089 SLNet::OP_DELETE(root->item, file, line);
1090 SLNet::OP_DELETE(root, file, line);
1091 root = 0;
1092 BinarySearchTree_size = 0;
1093 }
1094
1095 else
1096 {
1097 if ( current->left != 0 )
1098 {
1099 current = current->left;
1100 }
1101
1102 else
1103 if ( current->right != 0 )
1104 {
1105 current = current->right;
1106 }
1107
1108 else // leaf
1109 {
1110 // Not root node so must have a parent
1111 parent = FindParent( *( current->item ) );
1112
1113 if ( ( parent->left ) == current )
1114 parent->left = 0;
1115 else
1116 parent->right = 0;
1117
1118 SLNet::OP_DELETE(current->item, file, line);
1119
1120 SLNet::OP_DELETE(current, file, line);
1121
1122 current = parent;
1123
1124 BinarySearchTree_size--;
1125 }
1126 }
1127 }
1128 }
1129
1130 } // End namespace
1131
1132 #endif