ScapeGoatTree
Loading...
Searching...
No Matches
scapegoat_tree.tpp
Go to the documentation of this file.
1//
2// Created by DELL on 24/12/2025.
3//
4
5#ifndef TREE_SCAPEGOATTREE_TPP
6#define TREE_SCAPEGOATTREE_TPP
7#include "queue.hpp"
8#include "sstream"
9//==================================IMPLEMENTATION========================================================
10// =====================
11// Constructors
12// =====================
13
17template<typename T>
19
20template<typename T>
22 if (alpha > 1 or alpha < 0.5)return;
23 ALPHA = alpha;
24}
25
29template<typename T>
31 if (!Otree.root) return;
32 preorderTraversal(Otree.root);
33}
37template<typename T>
39 postorderTraversal(root);
40 max_nodes = 0;
41}
45template<typename T>
47 : root(other.root),
48nNodes(other.nNodes),
49max_nodes(other.max_nodes) {
50 other.root = nullptr;
51 other.nNodes = 0;
52 other.max_nodes = 0;
53}
54
55// =====================
56// Insert
57// =====================
58
62template <typename T>
64 //find the scapegoat node
65 TreeNode* goat = findTraitor(newNode->parent);
66 if (goat == nullptr) return;
67 T* temp_array = new T[nNodes];
68 int i = 0;
69 //flatten the tree into a sorted array
70 inorderTraversal(goat, i, temp_array);
71 const int sub_size = i; // size of subtree
72 //rebuild the subtree
73 TreeNode* balanced = rebuildTree(0, sub_size- 1, goat->parent, temp_array);
74 rebuildCount++;
75 //reattach the rebuilt subtree
76 if (!goat->parent) root = balanced; // if goat is root then update root
77 else if (goat == goat->parent->left) goat->parent->left = balanced; //if goat is left child then update left pointer
78 else goat->parent->right = balanced; //if goat is right child then update right pointer
79 postorderTraversal(goat);// delete old subtree
80 delete[] temp_array;
81}
82
86template<typename T>
88 // Record the operation for undo if not currently undoing/redoing
89 if (!isUndoing) {
90 undoStack.push({OpType::Insert, value});
91 }
93 if (!root) {
94 root = new TreeNode(value, nullptr);
95 nNodes++;
96 if (nNodes > max_nodes) max_nodes = nNodes;
97 return;
98 }
99
100 TreeNode* current = root;
101 TreeNode* parent = nullptr;
102 int depth = 0;
103
104 while (current) {
105 path.push_back(current);
106 parent = current;
107 ++current->size;
108 depth++;
110 current = current->left;
111 else if (value > current->value)
112 current = current->right;
113 else {
114 // value already exists, backtrack size increment
115 for (int i = 0; i < path.size(); i++) {
116 --path[i]->size;
117 }
118 // If the value already exists, we didn't actually change the tree,
119 // so we remove the command from the undo stack.
120 if (!isUndoing) {
121 undoStack.pop();
122 }
123 return;
124 }
125 }
126 auto* newNode = new TreeNode(value, parent);
128 parent->left = newNode;
129 else
130 parent->right = newNode;
131
132 nNodes++;
133 if (nNodes > max_nodes) max_nodes = nNodes;
134
135 if (depth + 1 <= getThreshold()) return;
136 restructure_subtree(newNode);
137}
141template<typename T>
143 // Group multiple insertions into a single undo/redo unit
144 if (!isUndoing) undoStack.push({OpType::BatchStart, T()});
145
146 for (int i = 0; i < values.size(); i++) {
147 insert(values[i]);
148 }
149 if (!isUndoing) undoStack.push({OpType::BatchEnd, T()});
150}
151
155template<typename T>
157 // Group multiple deletions into a single undo/redo unit
158 if (!isUndoing) undoStack.push({OpType::BatchStart, T()});
159 for (int i = 0; i < values.size(); i++) {
160 deleteValue(values[i]);
161 }
162 if (!isUndoing) undoStack.push({OpType::BatchEnd, T()});
163}
164
165
166// =====================
167// Delete
168// =====================
169
173template<typename T>
175 TreeNode* node = root;
176 TreeNode* parent = nullptr;
177
178 // Step 1: Search for the node
179 while (node != nullptr and node->value != value) {
180 parent = node;
182 node = node->left;
183 else
184 node = node->right;
185 }
186
187 // Value not found
188 if (!node) return false;
189
190 // Record the operation for undo if not currently undoing/redoing
191 if (not isUndoing) {
192 undoStack.push({OpType::Delete, value});
193 }
194 bool originalIsUndoing = isUndoing;
195 isUndoing = true;
196 // Case 1: Leaf node
197 if (!node->left && !node->right) {
198 // Decrement size for all nodes on the path
199 TreeNode* temp = root;
200 while (temp != node) {
201 --temp->size;
202 if (value < temp->value) temp = temp->left;
203 else temp = temp->right;
204 }
205 if (!parent) {
206 root = nullptr;
207 }
208 else if (parent->left == node) {
209 parent->left = nullptr;
210 }
211 else {
212 parent->right = nullptr;
213 }
214 delete node;
215 }
216
217 // Case 2: One child
218 else if(node->left && !node->right || !node->left && node->right) {
219 // Decrement size for all nodes on the path
220 TreeNode* temp = root;
221 while (temp != node) {
222 --temp->size;
223 if (value < temp->value) temp = temp->left;
224 else temp = temp->right;
225 }
226 TreeNode* child = nullptr;
227
228 if (node->left != nullptr)
229 child = node->left;
230 else
231 child = node->right;
232
233 child->parent = parent;
234
235 if (!parent) {
236 root = child;
237 }
238 else if (parent->left == node) {
239 parent->left = child;
240 }
241 else {
242 parent->right = child;
243 }
244
245 delete node;
246 }
247 // Case 3: Two children
248 else if (node->left && node->right) {
249 // Find inorder successor (smallest in right subtree)
250 TreeNode* suc = node->right;
251 while (suc->left != nullptr)
252 suc = suc->left;
253
255 deleteValue(successorValue);
257 isUndoing = originalIsUndoing;
258 return true;
259 }
260
261 // Update node count
262 nNodes--;
263 if (nNodes == 0) {
264 root = nullptr;
265 max_nodes = 0;
266 } else {
267 DeletionRebuild();
268 }
269 isUndoing = originalIsUndoing;
270 return true;
271}
272
273// =====================
274// Utility / Static helpers
275// =====================
276
280template<typename T>
282 if (!node) return -1;
283 const int max = findH(node->left) > findH(node->right) ? findH(node->left) :findH(node->right);
284 return 1+ max;
285}
286
290template<typename T>
292 if (!node) return 0;
293 return node->size;
294}
295
299template<typename T>
301 while (node != nullptr) {
302 const int left = countN(node->left);
303 const int right = countN(node->right);
304 int size = node->size;
305
306 if (left > ALPHA * size || right > ALPHA * size)
307 return node;
308
309 node = node->parent;
310 }
311 return nullptr;
312}
313
317template<typename T>
319 if (start > end) return nullptr; // base case
320 int mid = (start + end) / 2; // find mid index
321 auto* Nroot = new TreeNode(array[mid], parent_node); // create node with mid value
322 Nroot->left = rebuildTree(start, mid - 1, Nroot, array); // build left subtree
323 Nroot->right = rebuildTree(mid + 1, end, Nroot, array);// build right subtree
324 Nroot->size = 1 + countN(Nroot->left) + countN(Nroot->right);// update size
325 return Nroot;
326}
330template<typename T>
332 if (nNodes < 0.5 * max_nodes&& nNodes > 0) { // α = 0.5 for deletion
333 auto temp_array = new T[nNodes];
334 int i = 0;
335 inorderTraversal(root, i, temp_array);
336 const TreeNode* oldRoot = root;
337 root = rebuildTree(0, nNodes - 1, nullptr, temp_array);
338 rebuildCount++;
339 postorderTraversal(oldRoot);
340 max_nodes = nNodes;
341 delete[] temp_array;
342 }
343 }
347template<typename T>
351
352// =====================
353// Traversals
354// =====================
355
359template<typename T>
361if (!node) return;
362 inorderTraversal(node->left, i,array);
363 array[i++]= node->value;
364 inorderTraversal(node->right, i,array);
365}
366
370template<typename T>
372 if (!node) return;
373 postorderTraversal(node->left);
374 postorderTraversal(node->right);
375 delete node;
376}
377
381template<typename T>
383 if (!node) return;
384 insert(node->value);
385 preorderTraversal(node->left);
386 preorderTraversal(node->right);
387}
388
389// =====================
390// Display (internal)
391// =====================1
392
396template<typename T>
397// diplay order w ostream (output stream)
399 if (!node) return; // lw mfesh node bn return
400 os << node->value << " ";
401 displayPreOrder(node->left, os);
402 displayPreOrder(node->right, os);
403}
404
408template<typename T>
410 if (!node) return;
411 displayInOrder(node->left, os);
412 os << node->value << " ";
413 displayInOrder(node->right, os);
414}
415
419template<typename T>
421 if (!node) return;
422 displayPostOrder(node->left, os);
423 displayPostOrder(node->right, os);
424 os << node->value << " ";
425}
426
427// =====================
428// Display (public)
429// =====================
430
434template<typename T>
436 if (!root) return "Tree is empty.";
437 std::ostringstream oss;
438 displayPreOrder(root, oss);
439 return oss.str();
440}
441
445template<typename T>
447 if (!root) return "Tree is empty.";
448 std::ostringstream oss;
449 displayInOrder(root, oss);
450 return oss.str();
451}
452
456template<typename T>
458 if (!root) return "Tree is empty.";
459 std::ostringstream oss;
460 displayPostOrder(root, oss);
461 return oss.str();
462}
463
467template<typename T>
469 if (!root) return "Tree is Empty.";
470 std::string result;
472 q.push(root);
473 int level =0;
474
475 while (!q.isEmpty()) {
476 result += "Level " + std::to_string(level++) + ": "; // mn int l string b3dha bnro7 ll lvl ele ablo
477 const int nodesAtLevel = q.size();
478 for (int i = 0; i < nodesAtLevel; i++) {
479 TreeNode* curr = q.front(); // current node
480 q.pop(); // pop 3shan nshof el node ele b3dha
481
482 std::ostringstream oss;
483 oss << curr->value;
484 result += oss.str() + " "; // str 3shan n7wlo string
485
486 if (curr->left) q.push(curr->left);
487 if (curr->right) q.push(curr->right);
488 }
489 result += "\n";
490 }
491 return result;
492}
493
494
495
496// =====================
497// Operators
498// =====================
499
503template<typename T>
506 T* array = new T[nNodes];
507 T* other_array = new T[other.nNodes];
508 int i = 0;
509 inorderTraversal(root, i, array);
510 int i2 = 0;
511 other.inorderTraversal(other.root, i2, other_array);
512 T* temp_array = new T[nNodes + other.nNodes];
513 int idx = 0, idx1 = 0, idx2 = 0;
514
515 // Linear Merge (O(N+M)) to keep the array sorted
522 while (idx1 < nNodes && idx2 < other.nNodes) { //run as long as both arrays have elements
524 else if (array[idx1] > other_array[idx2]) temp_array[idx++] = other_array[idx2++];
525 else { // duplicates
526 temp_array[idx++] = array[idx1++];
527 idx2++;
528 }
529 }
530 while (idx1 < nNodes) temp_array[idx++] = array[idx1++]; //append remaining elements from first array
531 while (idx2 < other.nNodes) temp_array[idx++] = other_array[idx2++]; //append remaining elements from second array
532
533 //Rebuild (O(N+M))
534 result.root = result.rebuildTree(0, idx - 1, nullptr, temp_array);
535 result.nNodes = idx;
536 result.max_nodes = idx;
537 delete[] temp_array;
538 delete[] array;
539 delete[] other_array;
540 return result;
541}
542
546template<typename T>
548 if (this == &other) return *this;
549 postorderTraversal(root);
550 max_nodes = 0;
551 if (other.root) preorderTraversal(other.root);
552 return *this;
553}
554
558template<typename T>
560 if (this == &other) return *this;
561 postorderTraversal(root);
562 root = other.root;
563 nNodes = other.nNodes;
564 max_nodes = other.max_nodes;
565
566 other.root = nullptr;
567 other.nNodes = 0;
568 other.max_nodes = 0;
569
570 return *this;
571}
572
576template<typename T>
577void ScapeGoatTree<T>::operator+(const T& value) { insert(value); }
578
582template<typename T>
583void ScapeGoatTree<T>::operator+=(const T& value) { insert(value); }
584
588template<typename T>
589bool ScapeGoatTree<T>::operator-=(const T& value) { return deleteValue(value); }
590
594template<typename T>
596 return search(value);
597}
601template<typename T>
603 if (value == 0) {
604 clear();
605 }
606 return *this;
607}
611template<typename T>
613 return areTreesEqual(root, tree.root);
614}
618template<typename T>
620 // Both null = equal
621 if (!n1 && !n2) return true;
622
623 // One null, one not = unequal
624 if (!n1 || !n2) return false;
625
626 // Values differ = unequal
627 if (n1->value != n2->value) return false;
628
629 // Recursively check subtrees (in-order comparison)
630 return areTreesEqual(n1->left, n2->left) &&
631 areTreesEqual(n1->right, n2->right);
632}
636template<typename T>
638 return !(*this == tree);
639}
640
644template<typename T>
646 return root == nullptr;
647}
648
652template<typename T>
653bool ScapeGoatTree<T>::operator-(const T &value) {
654 return deleteValue(value);
655}
656
657// =====================
658// Balance / Search
659// =====================
660
664template<typename T>
665std::string ScapeGoatTree<T>::isBalanced() const {
666 std::ostringstream out;
667
668 const double n = countN(root);
669 if (n == 0) {
670 out << "Tree empty. Of course it's balanced ";
671 return out.str();
672 }
673
674 int height = findH(root);
675 double bound = log(n) / log(1.5);
676
677
678 out << "Node count: " << n << "\n";
679 out << "Height: " << height << "\n";
680 out << "Height bound: " << bound << "\n";
681 out << "Total Rebuilds: " << rebuildCount << "\n\n";
682
683 if (height<= bound)
684 out << "^_____^ Tree is balanced. \nCongratulations, It's not a Linked List.\n";
685 else
686 out << "~_~ Tree is NOT balanced. A scapegoat must be sacrificed.\n";
687
688 return out.str();
689}
690
694template<typename T>
695bool ScapeGoatTree<T>::search(const T& key) const {
696 TreeNode* current = root;
697 while (current != nullptr) {
698 if (key == current->value) return true;
700
701 else if (key > current->value) current = current->right;
702
703 }
704 return false;
705}
706
707template<typename T>
709 TreeNode* current = root;
710 while (current != nullptr) {
711 if (key == current->value) return current;
713
714 else if (key > current->value) current = current->right;
715
716 }
717 return nullptr;
718}
719
723template<typename T>
725 postorderTraversal(root);
726 root = nullptr;
727 nNodes = 0;
728 max_nodes = 0;
729}
735template<typename T>
737 if (undoStack.isEmpty()) return;
738 // Set flag to prevent undo actions from being recorded as new operations
739 isUndoing = true;
740 Command<T> cmd = undoStack.pop();
741
742 if (cmd.type == OpType::BatchEnd) {
743 // Handle batch operation: undo everything until BatchStart
744 redoStack.push(cmd); // Push End first to maintain order for redo
745 while (!undoStack.isEmpty()) {
746 Command<T> batchCmd = undoStack.pop();
747 redoStack.push(batchCmd);
748 if (batchCmd.type == OpType::BatchStart) break;
749
750 // Execute the inverse of the recorded operation
751 if (batchCmd.type == OpType::Insert) deleteValue(batchCmd.value);
752 else if (batchCmd.type == OpType::Delete) insert(batchCmd.value);
753 }
754 } else {
755 // Handle single operation
756 redoStack.push(cmd);
757 if (cmd.type == OpType::Insert) deleteValue(cmd.value);
758 else if (cmd.type == OpType::Delete) insert(cmd.value);
759 }
760 isUndoing = false;
761 }
766 template<typename T>
768 if (redoStack.isEmpty()) return;
769 // Set flag to prevent redo actions from being recorded in undoStack incorrectly
770 isUndoing = true;
771 Command<T> cmd = redoStack.pop();
772
773 if (cmd.type == OpType::BatchStart) {
774 // Handle batch operation: redo everything until BatchEnd
775 undoStack.push(cmd);
776 while (!redoStack.isEmpty()) {
777 Command<T> batchCmd = redoStack.pop();
778 undoStack.push(batchCmd);
779 if (batchCmd.type == OpType::BatchEnd) break;
780
781 // Re-execute the original operation
782 if (batchCmd.type == OpType::Insert) insert(batchCmd.value);
783 else if (batchCmd.type == OpType::Delete) deleteValue(batchCmd.value);
784 }
785 } else {
786 // Handle single operation
787 undoStack.push(cmd);
788 if (cmd.type == OpType::Insert) insert(cmd.value);
789 else if (cmd.type == OpType::Delete) deleteValue(cmd.value);
790 }
791 isUndoing = false;
792 }
793
794template<typename T>
796 T sum {};
797 if (!node)return 0;
798 if (node->value >= min)sum+=sumHelper(node->left,min,max);
799 if (node->value >= min && node->value <= max )sum+=node->value;
800 if (node->value <= max)sum+=sumHelper(node->right,min,max);
801 return sum;
802
803}
804
805template<typename T>
807 return sumHelper(root,min,max);
808}
809
810template<typename T>
812 if (!root)throw std::runtime_error("Tree is Empty");
813 TreeNode* current = root;
814 while (current->left) current =current->left;
815 return current->value;
816
817}
818template<typename T>
820 if (!root)throw std::exception("Tree is Empty");
821 TreeNode* current = root;
822 while (current->right) current =current->right;
823 return current->value;
824}
825
826template<typename T>
828 if (!node)return;
829 if (node->value > min)rangeHelper(node->left,min,max,range);
830 if (node->value >= min && node->value <= max )range.push_back(node->value);
831 if (node->value < max)rangeHelper(node->right,min,max,range);
832}
833template<typename T>
836 rangeHelper(root,min,max,range);
837 return std::move(range);
838}
839//leftmost in the right subtree.
840template<typename T>
842 TreeNode* current = root;
843 TreeNode* successor = nullptr;
844 while (current) {
845 if (current->value > value) {
847 current = current->left;
848 } else {
849 current = current->right;
850 }
851 }
852 if (!successor) throw std::runtime_error("No successor found");
853 return successor->value;
854}
855
856template<typename T>
858 int leftSize = countN(node->left);
859 if (k == leftSize + 1) return node->value;
860 if (k <= leftSize) return kthSmallestHelper(node->left, k);
861 return kthSmallestHelper(node->right, k - leftSize - 1);
862}
863template<typename T>
865 if (k < 1 || k > nNodes) throw std::out_of_range("k is out of bounds");
866 return kthSmallestHelper(root, k);
867}
868
869template<typename T>
871 if (!root) return end();
872 TreeNode* curr = root;
873 while (curr->left)curr = curr->left;
874 return iterator(curr);
875}
876template<typename T>
880
881template<typename T>
883 if (!node)return nullptr;
884
885 if (node->right) {
886 TreeNode* suc = node->right;
887 while (suc->left != nullptr)
888 suc = suc->left;
889 return suc;
890 }
891 TreeNode* p = node->parent;
892 while ( p && node == p->right) {
893 node = p;
894 p = p->parent;
895 }
896 return p;
897}
898
899template<typename T>
901 if (node == nullptr)
902 return 0;
903
904 // Find the size of left and right
905 // subtree.
906 const int left = updateSize(node->left);
907 const int right = updateSize(node->right);
908
909 // the size of curr subtree.
910 node->size = left+right+1;
911 return node->size;
912}
913
914template<typename T>
915std::pair<ScapeGoatTree<T>, ScapeGoatTree<T> > ScapeGoatTree<T>::split(T value) {
916 TreeNode* node = find_node(value);
917 if (!node)return {ScapeGoatTree{}, ScapeGoatTree{}};
920 if (TreeNode* parent = node->parent) {
921 if (parent->left == node) parent->left = nullptr;
922 if (parent->right == node) parent->right = nullptr;
923 }
924 tree1.root = node->left;
925 tree2.root = node->right;
926 updateSize(tree1.root);
927 updateSize(tree2.root);
928 int size1 = tree1.root ? tree1.root->size : 0;
929 int size2 = tree2.root ? tree2.root->size : 0;
930
931 T* array1 = size1 ? new T[size1] : nullptr;
932 T* array2 = size2 ? new T[size2] : nullptr;
933 int i = 0, j =0;
934 inorderTraversal(tree1.root,i,array1);
935 tree1.root= rebuildTree(0, i-1,nullptr,array1);
936
937 inorderTraversal(tree2.root,j,array2);
938 tree2.root = rebuildTree(0, j-1,nullptr,array2);
939 delete[] array1;
940 delete[] array2;
941 return {tree1,tree2};
942}
943
944#endif //TREE_SCAPEGOATTREE_TPP
Definition Node.hpp:8
T value
Definition Node.hpp:10
Node * right
Definition Node.hpp:12
Node * left
Definition Node.hpp:11
Definition queue.hpp:9
T value
Definition queue.hpp:11
Definition scapegoat_tree.hpp:75
Definition scapegoat_tree.hpp:53
T sumHelper(TreeNode *node, T min, T max)
Definition scapegoat_tree.tpp:795
std::string displayInOrder()
Definition scapegoat_tree.tpp:446
std::string displayLevels()
Definition scapegoat_tree.tpp:468
bool operator-(const T &value)
Definition scapegoat_tree.tpp:653
T getMin()
Definition scapegoat_tree.tpp:811
bool operator==(const ScapeGoatTree &tree) const
Definition scapegoat_tree.tpp:612
static iterator end()
Definition scapegoat_tree.tpp:877
T kthSmallestHelper(TreeNode *node, int k) const
Definition scapegoat_tree.tpp:857
void inorderTraversal(const TreeNode *node, int &i, T *&array) const
Definition scapegoat_tree.tpp:360
void rangeHelper(TreeNode *node, T min, T max, Vector< T > &range)
Definition scapegoat_tree.tpp:827
TreeNode * findTraitor(TreeNode *node)
Definition scapegoat_tree.tpp:300
ScapeGoatTree & operator=(const ScapeGoatTree &other)
Definition scapegoat_tree.tpp:547
ScapeGoatTree operator+(const ScapeGoatTree &other) const
Definition scapegoat_tree.tpp:504
T kthSmallest(int k) const
Definition scapegoat_tree.tpp:864
int updateSize(TreeNode *&node)
Definition scapegoat_tree.tpp:900
bool operator!() const
Definition scapegoat_tree.tpp:645
TreeNode * rebuildTree(int start, int end, TreeNode *parent_node, T *array)
Definition scapegoat_tree.tpp:318
bool operator[](T value) const
Definition scapegoat_tree.tpp:595
const TreeNode * getRoot()
Definition scapegoat_tree.tpp:348
T sumInRange(T min, T max)
Definition scapegoat_tree.tpp:806
iterator begin()
Definition scapegoat_tree.tpp:870
void undo()
Definition scapegoat_tree.tpp:736
Vector< T > valuesInRange(T min, T max)
Definition scapegoat_tree.tpp:834
void insertBatch(const Vector< T > &values)
Definition scapegoat_tree.tpp:142
void operator+=(const T &value)
Definition scapegoat_tree.tpp:583
~ScapeGoatTree()
Definition scapegoat_tree.tpp:38
static unsigned int countN(const TreeNode *node)
Definition scapegoat_tree.tpp:291
void clear()
Definition scapegoat_tree.tpp:724
std::pair< ScapeGoatTree, ScapeGoatTree > split(T value)
Definition scapegoat_tree.tpp:915
static TreeNode * findSuccessor(TreeNode *node)
Definition scapegoat_tree.tpp:882
void restructure_subtree(TreeNode *newNode)
Definition scapegoat_tree.tpp:63
T getSuccessor(T value) const
Definition scapegoat_tree.tpp:841
std::string isBalanced() const
Definition scapegoat_tree.tpp:665
void deleteBatch(const Vector< T > &values)
Definition scapegoat_tree.tpp:156
TreeNode * find_node(T &key) const
Definition scapegoat_tree.tpp:708
static void postorderTraversal(const TreeNode *node)
Definition scapegoat_tree.tpp:371
bool areTreesEqual(const TreeNode *n1, const TreeNode *n2) const
Definition scapegoat_tree.tpp:619
void DeletionRebuild()
Definition scapegoat_tree.tpp:331
void redo()
Definition scapegoat_tree.tpp:767
bool search(const T &key) const
Definition scapegoat_tree.tpp:695
void preorderTraversal(const TreeNode *node)
Definition scapegoat_tree.tpp:382
T getMax()
Definition scapegoat_tree.tpp:819
std::string displayPostOrder()
Definition scapegoat_tree.tpp:457
std::string displayPreOrder()
Definition scapegoat_tree.tpp:435
bool operator!=(const ScapeGoatTree &tree) const
Definition scapegoat_tree.tpp:637
bool deleteValue(T value)
Definition scapegoat_tree.tpp:174
bool operator-=(const T &value)
Definition scapegoat_tree.tpp:589
static int findH(const TreeNode *node)
Definition scapegoat_tree.tpp:281
void insert(T value)
Definition scapegoat_tree.tpp:87
@ BatchStart