CppCommon  1.0.4.1
C++ Common Library
bintree_avl.inl
Go to the documentation of this file.
1 
9 namespace CppCommon {
10 
11 template <typename T, typename TCompare>
12 template <class InputIterator>
13 inline BinTreeAVL<T, TCompare>::BinTreeAVL(InputIterator first, InputIterator last, const TCompare& compare) noexcept
14  : _compare(compare)
15 {
16  for (auto it = first; it != last; ++it)
17  insert(*it);
18 }
19 
20 template <typename T, typename TCompare>
21 inline T* BinTreeAVL<T, TCompare>::lowest() noexcept
22 {
23  return (T*)InternalLowest();
24 }
25 
26 template <typename T, typename TCompare>
27 inline const T* BinTreeAVL<T, TCompare>::lowest() const noexcept
28 {
29  return InternalLowest();
30 }
31 
32 template <typename T, typename TCompare>
33 inline const T* BinTreeAVL<T, TCompare>::InternalLowest() const noexcept
34 {
35  const T* result = _root;
36  if (result != nullptr)
37  while (result->left != nullptr)
38  result = result->left;
39  return result;
40 }
41 
42 template <typename T, typename TCompare>
44 {
45  return (T*)InternalHighest();
46 }
47 
48 template <typename T, typename TCompare>
49 inline const T* BinTreeAVL<T, TCompare>::highest() const noexcept
50 {
51  return InternalHighest();
52 }
53 
54 template <typename T, typename TCompare>
55 inline const T* BinTreeAVL<T, TCompare>::InternalHighest() const noexcept
56 {
57  const T* result = _root;
58  if (result != nullptr)
59  while (result->right != nullptr)
60  result = result->right;
61  return result;
62 }
63 
64 template <typename T, typename TCompare>
66 {
67  return iterator(this, lowest());
68 }
69 
70 template <typename T, typename TCompare>
72 {
73  return const_iterator(this, lowest());
74 }
75 
76 template <typename T, typename TCompare>
78 {
79  return const_iterator(this, lowest());
80 }
81 
82 template <typename T, typename TCompare>
84 {
85  return iterator(this, nullptr);
86 }
87 
88 template <typename T, typename TCompare>
90 {
91  return const_iterator(this, nullptr);
92 }
93 
94 template <typename T, typename TCompare>
96 {
97  return const_iterator(this, nullptr);
98 }
99 
100 template <typename T, typename TCompare>
102 {
103  return reverse_iterator(this, highest());
104 }
105 
106 template <typename T, typename TCompare>
108 {
109  return const_reverse_iterator(this, highest());
110 }
111 
112 template <typename T, typename TCompare>
114 {
115  return const_reverse_iterator(this, highest());
116 }
117 
118 template <typename T, typename TCompare>
120 {
121  return reverse_iterator(this, nullptr);
122 }
123 
124 template <typename T, typename TCompare>
126 {
127  return const_reverse_iterator(this, nullptr);
128 }
129 
130 template <typename T, typename TCompare>
132 {
133  return const_reverse_iterator(this, nullptr);
134 }
135 
136 template <typename T, typename TCompare>
138 {
139  return iterator(this, (T*)InternalFind(item));
140 }
141 
142 template <typename T, typename TCompare>
143 inline typename BinTreeAVL<T, TCompare>::const_iterator BinTreeAVL<T, TCompare>::find(const T& item) const noexcept
144 {
145  return const_iterator(this, InternalFind(item));
146 }
147 
148 template <typename T, typename TCompare>
149 inline const T* BinTreeAVL<T, TCompare>::InternalFind(const T& item) const noexcept
150 {
151  // Perform the binary tree search from the root node
152  const T* current = _root;
153 
154  while (current != nullptr)
155  {
156  // Move to the left subtree
157  if (compare(item, *current))
158  {
159  current = current->left;
160  continue;
161  }
162 
163  // Move to the right subtree
164  if (compare(*current, item))
165  {
166  current = current->right;
167  continue;
168  }
169 
170  // Found result node
171  return current;
172  }
173 
174  // Nothing was found...
175  return nullptr;
176 }
177 
178 template <typename T, typename TCompare>
180 {
181  return iterator(this, (T*)InternalLowerBound(item));
182 }
183 
184 template <typename T, typename TCompare>
186 {
187  return const_iterator(this, InternalLowerBound(item));
188 }
189 
190 template <typename T, typename TCompare>
191 inline const T* BinTreeAVL<T, TCompare>::InternalLowerBound(const T& item) const noexcept
192 {
193  // Perform the binary tree search from the root node
194  const T* current = _root;
195  const T* previous = nullptr;
196 
197  while (current != nullptr)
198  {
199  // Move to the left subtree
200  if (compare(item, *current))
201  {
202  previous = current;
203  current = current->left;
204  continue;
205  }
206 
207  // Move to the right subtree
208  if (compare(*current, item))
209  {
210  current = current->right;
211  continue;
212  }
213 
214  // Found result node
215  return current;
216  }
217 
218  // Return the previous lower bound node if any met
219  return previous;
220 }
221 
222 template <typename T, typename TCompare>
224 {
225  return iterator(this, (T*)InternalUpperBound(item));
226 }
227 
228 template <typename T, typename TCompare>
230 {
231  return const_iterator(this, InternalUpperBound(item));
232 }
233 
234 template <typename T, typename TCompare>
235 inline const T* BinTreeAVL<T, TCompare>::InternalUpperBound(const T& item) const noexcept
236 {
237  // Perform the binary tree search from the root node
238  const T* current = _root;
239  const T* previous = nullptr;
240 
241  while (current != nullptr)
242  {
243  // Move to the left subtree
244  if (compare(item, *current))
245  {
246  previous = current;
247  current = current->left;
248  continue;
249  }
250 
251  // Move to the right subtree
252  current = current->right;
253  }
254 
255  // Return the previous upper bound node if any met
256  return previous;
257 }
258 
259 template <typename T, typename TCompare>
260 inline std::pair<typename BinTreeAVL<T, TCompare>::iterator, bool> BinTreeAVL<T, TCompare>::insert(T& item) noexcept
261 {
262  return insert(const_iterator(this, _root), item);
263 }
264 
265 template <typename T, typename TCompare>
266 inline std::pair<typename BinTreeAVL<T, TCompare>::iterator, bool> BinTreeAVL<T, TCompare>::insert(const const_iterator& position, T& item) noexcept
267 {
268  // Perform the binary tree insert from the given node
269  T* current = (T*)position.operator->();
270 
271  while (current != nullptr)
272  {
273  // Move to the left subtree
274  if (compare(item, *current))
275  {
276  if (current->left != nullptr)
277  {
278  current = current->left;
279  continue;
280  }
281  else
282  {
283  // Link a new item to the left leaf
284  current->left = &item;
285  break;
286  }
287  }
288 
289  // Move to the right subtree
290  if (compare(*current, item))
291  {
292  if (current->right != nullptr)
293  {
294  current = current->right;
295  continue;
296  }
297  else
298  {
299  // Link a new item to the right leaf
300  current->right = &item;
301  break;
302  }
303  }
304 
305  // Found duplicate node
306  return std::make_pair(iterator(this, current), false);
307  }
308 
309  item.parent = current;
310  item.left = nullptr;
311  item.right = nullptr;
312  if (_root == nullptr)
313  _root = &item;
314  ++_size;
315 
316  // Balance the binary tree
317  T* node = &item;
318  node->balance = 0;
319  while (node->parent != nullptr)
320  {
321  // Rule 1
322  if (((node->parent != nullptr) && (node->parent->left == node)) && (node->parent->balance == 0))
323  {
324  node->parent->balance = -1;
325  node = node->parent;
326  continue;
327  }
328  if (((node->parent != nullptr) && (node->parent->right == node)) && (node->parent->balance == 0))
329  {
330  node->parent->balance = 1;
331  node = node->parent;
332  continue;
333  }
334 
335  // Rule 2
336  if (((node->parent != nullptr) && (node->parent->left == node)) && (node->parent->balance == 1))
337  {
338  node->parent->balance = 0;
339  break;
340  }
341  if (((node->parent != nullptr) && (node->parent->right == node)) && (node->parent->balance == -1))
342  {
343  node->parent->balance = 0;
344  break;
345  }
346 
347  // Rule 3
348  if (((node->parent != nullptr) && (node->parent->left == node)) && (node->parent->balance == -1))
349  {
350  if (node->balance == 1)
351  RotateLeftLeft(node->parent);
352  else
353  RotateRight(node->parent);
354  break;
355  }
356  if (((node->parent != nullptr) && (node->parent->right == node)) && (node->parent->balance == 1))
357  {
358  if (node->balance == -1)
359  RotateRightRight(node->parent);
360  else
361  RotateLeft(node->parent);
362  break;
363  }
364  }
365 
366  // Correct AVL balanced binary tree root
367  while (_root->parent != nullptr)
368  _root = _root->parent;
369 
370  return std::make_pair(iterator(this, &item), true);
371 }
372 
373 template <typename T, typename TCompare>
374 inline T* BinTreeAVL<T, TCompare>::erase(const T& item) noexcept
375 {
376  return erase(find(item)).operator->();
377 }
378 
379 template <typename T, typename TCompare>
381 {
382  T* result = ((iterator&)it).operator->();
383  if (result == nullptr)
384  return end();
385 
386  T* node = result;
387  T* start = nullptr;
388 
389  // If we want to delete the root item, we have to do some extra operation the preserve some pointers...
390  if (node->parent == nullptr)
391  {
392  // The root is the only one node in the tree
393  if ((node->left == nullptr) && (node->right == nullptr))
394  {
395  _root = nullptr;
396  node = nullptr;
397  }
398  }
399 
400  // Removed node has no children
401  if ((node != nullptr) && (node->left == nullptr) && (node->right == nullptr))
402  {
403  if (node->parent->left == node)
404  node->parent->left=nullptr;
405  else
406  node->parent->right=nullptr;
407  start = node->parent;
408  node = nullptr;
409  }
410 
411  // Removed node has only right son
412  if ((node != nullptr) && (node->left == nullptr) && (node->right != nullptr))
413  {
414  T* a = node->right;
415  if (node->parent == nullptr)
416  _root = a;
417  Swap(node, a);
418  node->right = nullptr;
419  start = node;
420  }
421 
422  // Removed node has only left son
423  if ((node != nullptr) && (node->left != nullptr) && (node->right == nullptr))
424  {
425  T* a = node->left;
426  if (node->parent == nullptr)
427  _root = a;
428  Swap(node, a);
429  node->left = nullptr;
430  start = node;
431  }
432 
433  // Removed node has both sons.
434  if ((node != nullptr) && (node->left != nullptr) && (node->right != nullptr))
435  {
436  T* a = node->left;
437  while (a->right != nullptr)
438  a = a->right;
439  T* b = a->left;
440 
441  if (node->parent == nullptr)
442  _root = a;
443  Swap(node, a);
444 
445  if (b != nullptr)
446  {
447  if (a->parent == nullptr)
448  _root = b;
449  Swap(a, b);
450  a->left = nullptr;
451  start = a;
452  }
453  else
454  {
455  if (a->parent->left == a)
456  a->parent->left = nullptr;
457  else
458  a->parent->right = nullptr;
459  start = a->parent;
460  }
461  }
462 
463  // Unlink the removed node
464  if (start != nullptr)
465  Unlink(start);
466 
467  // Correct AVL balanced binary tree root
468  if (_root != nullptr)
469  {
470  while (_root->parent != nullptr)
471  _root = _root->parent;
472  }
473 
474  result->parent = nullptr;
475  result->left = nullptr;
476  result->right = nullptr;
477  --_size;
478  return iterator(this, result);
479 }
480 
481 template <typename T, typename TCompare>
482 inline void BinTreeAVL<T, TCompare>::RotateLeft(T* node)
483 {
484  if (node->right == nullptr)
485  return;
486 
487  T* current = node->right;
488 
489  if (node->parent != nullptr)
490  {
491  if ((node->parent != nullptr) && (node->parent->left == node))
492  node->parent->left = current;
493  else
494  node->parent->right = current;
495  current->parent = node->parent;
496  }
497  else
498  current->parent = nullptr;
499  node->right = current->left;
500  current->left = node;
501  node->parent = current;
502  if (node->right != nullptr)
503  node->right->parent = node;
504 
505  if (current->balance == 0)
506  {
507  node->balance = 1;
508  current->balance = -1;
509  }
510  else
511  {
512  node->balance = 0;
513  current->balance = 0;
514  }
515 }
516 
517 template <typename T, typename TCompare>
518 inline void BinTreeAVL<T, TCompare>::RotateRight(T* node)
519 {
520  if (node->left == nullptr)
521  return;
522 
523  T* current = node->left;
524 
525  if (node->parent != nullptr)
526  {
527  if ((node->parent != nullptr) && (node->parent->left == node))
528  node->parent->left = current;
529  else
530  node->parent->right = current;
531  current->parent = node->parent;
532  }
533  else
534  current->parent = nullptr;
535  node->left = current->right;
536  current->right = node;
537  node->parent = current;
538  if (node->left != nullptr)
539  node->left->parent = node;
540 
541  if (current->balance == 0)
542  {
543  node->balance = -1;
544  current->balance = 1;
545  }
546  else
547  {
548  node->balance = 0;
549  current->balance = 0;
550  }
551 }
552 
553 template <typename T, typename TCompare>
554 inline void BinTreeAVL<T, TCompare>::RotateLeftLeft(T* node)
555 {
556  if ((node->left == nullptr) || (node->left->right == nullptr))
557  return;
558 
559  T* current = node->left;
560  T* next = node->left->right;
561 
562  if (node->parent != nullptr)
563  {
564  if ((node->parent != nullptr) && (node->parent->left == node))
565  node->parent->left = next;
566  else
567  node->parent->right = next;
568  }
569  current->right = next->left;
570  node->left = next->right;
571  next->left = current;
572  next->right = node;
573  next->parent = node->parent;
574  node->parent = next;
575  current->parent = next;
576  if (current->right != nullptr)
577  current->right->parent = current;
578  if (node->left != nullptr)
579  node->left->parent = node;
580 
581  switch (next->balance)
582  {
583  case -1:
584  node->balance = 1;
585  current->balance = 0;
586  break;
587  case 0:
588  node->balance = 0;
589  current->balance = 0;
590  break;
591  case 1:
592  node->balance = 0;
593  current->balance = -1;
594  break;
595  }
596  next->balance = 0;
597 }
598 
599 template <typename T, typename TCompare>
600 inline void BinTreeAVL<T, TCompare>::RotateRightRight(T* node)
601 {
602  if ((node->right == nullptr) || (node->right->left == nullptr))
603  return;
604 
605  T* current = node->right;
606  T* next = node->right->left;
607 
608  if (node->parent != nullptr)
609  {
610  if ((node->parent != nullptr) && (node->parent->left == node))
611  node->parent->left = next;
612  else
613  node->parent->right = next;
614  }
615  node->right = next->left;
616  current->left = next->right;
617  next->left = node;
618  next->right = current;
619  next->parent = node->parent;
620  node->parent = next;
621  current->parent = next;
622  if (node->right != nullptr)
623  node->right->parent = node;
624  if (current->left != nullptr)
625  current->left->parent = current;
626 
627  switch (next->balance)
628  {
629  case -1:
630  node->balance = 0;
631  current->balance = 1;
632  break;
633  case 0:
634  node->balance = 0;
635  current->balance = 0;
636  break;
637  case 1:
638  node->balance = -1;
639  current->balance = 0;
640  break;
641  }
642  next->balance = 0;
643 }
644 
645 template <typename T, typename TCompare>
646 inline void BinTreeAVL<T, TCompare>::Unlink(T* node)
647 {
648  // Rule 1
649  if ((node->balance == 0) && (node->left == nullptr))
650  {
651  node->balance = 1;
652  return;
653  }
654  if ((node->balance == 0) && (node->right == nullptr))
655  {
656  node->balance = -1;
657  return;
658  }
659 
660  // Rule 2
661  if ((node->balance == -1) && (node->left == nullptr))
662  node->balance = 0;
663  if ((node->balance == 1) && (node->right == nullptr))
664  node->balance = 0;
665 
666  // Rule 3
667  if ((node->balance == -1) && (node->right == nullptr))
668  {
669  if (node->left->balance == 1)
670  RotateLeftLeft(node);
671  else
672  RotateRight(node);
673  node = node->parent;
674  if (node->balance == 1)
675  return;
676  }
677  if ((node->balance == 1) && (node->left == nullptr))
678  {
679  if (node->right->balance == -1)
680  RotateRightRight(node);
681  else
682  RotateLeft(node);
683  node = node->parent;
684  if (node->balance == -1)
685  return;
686  }
687 
688  while (node->parent != nullptr)
689  {
690  // Rule 1
691  if (((node->parent != nullptr) && (node->parent->left == node)) && (node->parent->balance == 0))
692  {
693  node->parent->balance = 1;
694  break;
695  }
696  if (((node->parent != nullptr) && (node->parent->right == node)) && (node->parent->balance == 0))
697  {
698  node->parent->balance = -1;
699  break;
700  }
701 
702  // Rule 2
703  if (((node->parent != nullptr) && (node->parent->left == node)) && (node->parent->balance == -1))
704  {
705  node->parent->balance = 0;
706  node = node->parent;
707  continue;
708  }
709  if (((node->parent != nullptr) && (node->parent->right == node)) && (node->parent->balance == 1))
710  {
711  node->parent->balance = 0;
712  node = node->parent;
713  continue;
714  }
715 
716  // Rule 3
717  if (((node->parent != nullptr) && (node->parent->right == node)) && (node->parent->balance == -1))
718  {
719  if (node->parent->left->balance == 1)
720  RotateLeftLeft(node->parent);
721  else
722  RotateRight(node->parent);
723  node = node->parent->parent;
724  if (node->balance == 1)
725  return;
726  continue;
727  }
728  if (((node->parent != nullptr) && (node->parent->left == node)) && (node->parent->balance == 1))
729  {
730  if (node->parent->right->balance == -1)
731  RotateRightRight(node->parent);
732  else
733  RotateLeft(node->parent);
734  node = node->parent->parent;
735  if (node->balance == -1)
736  return;
737  continue;
738  }
739 
740  // Never happens...
741  break;
742  }
743 }
744 
745 template <typename T, typename TCompare>
746 inline void BinTreeAVL<T, TCompare>::Swap(T*& node1, T*& node2)
747 {
748  T* first_parent = node1->parent;
749  T* first_left = node1->left;
750  T* first_right = node1->right;
751  T* second_parent = node2->parent;
752  T* second_left = node2->left;
753  T* second_right = node2->right;
754  bool first_is_left = ((first_parent != nullptr) && (first_parent->left == node1));
755  bool second_is_left = ((second_parent != nullptr) && (second_parent->left == node2));
756 
757  // Update first node links
758  if (first_parent != nullptr)
759  {
760  if (first_is_left)
761  first_parent->left = node2;
762  else
763  first_parent->right = node2;
764  }
765  if (first_left != nullptr)
766  first_left->parent = node2;
767  if (first_right != nullptr)
768  first_right->parent = node2;
769 
770  // Update second node links
771  if (second_parent != nullptr)
772  {
773  if (second_is_left)
774  second_parent->left = node1;
775  else
776  second_parent->right = node1;
777  }
778  if (second_left != nullptr)
779  second_left->parent = node1;
780  if (second_right != nullptr)
781  second_right->parent = node1;
782 
783  // Swap node links
784  std::swap(node1->parent, node2->parent);
785  std::swap(node1->left, node2->left);
786  std::swap(node1->right, node2->right);
787  std::swap(node1->balance, node2->balance);
788 
789  // Swap nodes
790  std::swap(node1, node2);
791 }
792 
793 template <typename T, typename TCompare>
794 inline void BinTreeAVL<T, TCompare>::clear() noexcept
795 {
796  _size = 0;
797  _root = nullptr;
798 }
799 
800 template <typename T, typename TCompare>
801 inline void BinTreeAVL<T, TCompare>::swap(BinTreeAVL& bintree) noexcept
802 {
803  using std::swap;
804  swap(_compare, bintree._compare);
805  swap(_size, bintree._size);
806  swap(_root, bintree._root);
807 }
808 
809 template <typename T, typename TCompare>
810 inline void swap(BinTreeAVL<T, TCompare>& bintree1, BinTreeAVL<T, TCompare>& bintree2) noexcept
811 {
812  bintree1.swap(bintree2);
813 }
814 
815 } // namespace CppCommon
Intrusive balanced AVL binary tree container.
Definition: bintree_avl.h:100
T * lowest() noexcept
Get the lowest binary tree item.
Definition: bintree_avl.inl:21
T * erase(const T &item) noexcept
Erase the given item from the binary tree.
void clear() noexcept
Clear the binary tree.
const_reverse_iterator crbegin() const noexcept
reverse_iterator rend() noexcept
Get the reverse end binary tree iterator.
iterator lower_bound(const T &item) noexcept
Find the iterator which points to the first item that not less than the given item in the binary tree...
const_reverse_iterator crend() const noexcept
const_iterator cend() const noexcept
Definition: bintree_avl.inl:95
void swap(BinTreeAVL &bintree) noexcept
Swap two instances.
reverse_iterator rbegin() noexcept
Get the reverse begin binary tree iterator.
std::pair< iterator, bool > insert(T &item) noexcept
Insert a new item into the binary tree.
iterator end() noexcept
Get the end binary tree iterator.
Definition: bintree_avl.inl:83
T * highest() noexcept
Get the highest binary tree item.
Definition: bintree_avl.inl:43
const_iterator cbegin() const noexcept
Definition: bintree_avl.inl:77
BinTreeAVL(const TCompare &compare=TCompare()) noexcept
Definition: bintree_avl.h:127
iterator find(const T &item) noexcept
Find the iterator which points to the first equal item in the binary tree or return end iterator.
iterator begin() noexcept
Get the begin binary tree iterator.
Definition: bintree_avl.inl:65
iterator upper_bound(const T &item) noexcept
Find the iterator which points to the first item that greater than the given item in the binary tree ...
Intrusive binary tree constant iterator.
Definition: bintree.h:335
Intrusive binary tree constant reverse iterator.
Definition: bintree.h:448
Intrusive binary tree iterator.
Definition: bintree.h:279
Intrusive binary tree reverse iterator.
Definition: bintree.h:392
C++ Common project definitions.
Definition: token_bucket.h:15
void swap(FileCache &cache1, FileCache &cache2) noexcept
Definition: filecache.inl:23
void swap(BinTreeAVL< T, TCompare > &bintree1, BinTreeAVL< T, TCompare > &bintree2) noexcept