CppCommon 1.0.5.0
C++ Common Library
Loading...
Searching...
No Matches
bintree_avl.inl
Go to the documentation of this file.
1
9namespace CppCommon {
10
11template <typename T, typename TCompare>
12template <class InputIterator>
13inline 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
20template <typename T, typename TCompare>
22{
23 return (T*)InternalLowest();
24}
25
26template <typename T, typename TCompare>
27inline const T* BinTreeAVL<T, TCompare>::lowest() const noexcept
28{
29 return InternalLowest();
30}
31
32template <typename T, typename TCompare>
33inline 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
42template <typename T, typename TCompare>
44{
45 return (T*)InternalHighest();
46}
47
48template <typename T, typename TCompare>
49inline const T* BinTreeAVL<T, TCompare>::highest() const noexcept
50{
51 return InternalHighest();
52}
53
54template <typename T, typename TCompare>
55inline 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
64template <typename T, typename TCompare>
66{
67 return iterator(this, lowest());
68}
69
70template <typename T, typename TCompare>
72{
73 return const_iterator(this, lowest());
74}
75
76template <typename T, typename TCompare>
78{
79 return const_iterator(this, lowest());
80}
81
82template <typename T, typename TCompare>
84{
85 return iterator(this, nullptr);
86}
87
88template <typename T, typename TCompare>
90{
91 return const_iterator(this, nullptr);
92}
93
94template <typename T, typename TCompare>
96{
97 return const_iterator(this, nullptr);
98}
99
100template <typename T, typename TCompare>
102{
103 return reverse_iterator(this, highest());
104}
105
106template <typename T, typename TCompare>
108{
109 return const_reverse_iterator(this, highest());
110}
111
112template <typename T, typename TCompare>
114{
115 return const_reverse_iterator(this, highest());
116}
117
118template <typename T, typename TCompare>
120{
121 return reverse_iterator(this, nullptr);
122}
123
124template <typename T, typename TCompare>
126{
127 return const_reverse_iterator(this, nullptr);
128}
129
130template <typename T, typename TCompare>
132{
133 return const_reverse_iterator(this, nullptr);
134}
135
136template <typename T, typename TCompare>
138{
139 return iterator(this, (T*)InternalFind(item));
140}
141
142template <typename T, typename TCompare>
144{
145 return const_iterator(this, InternalFind(item));
146}
147
148template <typename T, typename TCompare>
149inline 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
178template <typename T, typename TCompare>
180{
181 return iterator(this, (T*)InternalLowerBound(item));
182}
183
184template <typename T, typename TCompare>
186{
187 return const_iterator(this, InternalLowerBound(item));
188}
189
190template <typename T, typename TCompare>
191inline 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
222template <typename T, typename TCompare>
224{
225 return iterator(this, (T*)InternalUpperBound(item));
226}
227
228template <typename T, typename TCompare>
230{
231 return const_iterator(this, InternalUpperBound(item));
232}
233
234template <typename T, typename TCompare>
235inline 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
259template <typename T, typename TCompare>
260inline 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
265template <typename T, typename TCompare>
266inline 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
373template <typename T, typename TCompare>
374inline T* BinTreeAVL<T, TCompare>::erase(const T& item) noexcept
375{
376 return erase(find(item)).operator->();
377}
378
379template <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
481template <typename T, typename TCompare>
482inline 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
517template <typename T, typename TCompare>
518inline 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
553template <typename T, typename TCompare>
554inline 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
599template <typename T, typename TCompare>
600inline 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
645template <typename T, typename TCompare>
646inline 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
745template <typename T, typename TCompare>
746inline 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
793template <typename T, typename TCompare>
794inline void BinTreeAVL<T, TCompare>::clear() noexcept
795{
796 _size = 0;
797 _root = nullptr;
798}
799
800template <typename T, typename TCompare>
801inline 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
809template <typename T, typename TCompare>
810inline 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.
T * lowest() noexcept
Get the lowest binary tree item.
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
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.
friend void swap(BinTreeAVL< U, UCompare > &bintree1, BinTreeAVL< U, UCompare > &bintree2) noexcept
iterator end() noexcept
Get the end binary tree iterator.
T * highest() noexcept
Get the highest binary tree item.
const_iterator cbegin() const noexcept
BinTreeAVL(const TCompare &compare=TCompare()) noexcept
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.
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.
void swap(FileCache &cache1, FileCache &cache2) noexcept
Definition filecache.inl:23