aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
AVLTree.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2026 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2026 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41
49
50#ifndef GUM_AVL_TREE_H
51#define GUM_AVL_TREE_H
52
53#include <algorithm>
54#include <string>
55
56#include <agrum/agrum.h>
57
60
61#include <initializer_list>
62
63namespace gum {
64
65#ifndef DOXYGEN_SHOULD_SKIP_THIS
66
67 template < typename Val, typename Cmp >
68 class AVLTreeIterator;
69 template < typename Val, typename Cmp >
71
72 template < typename Val, typename Cmp >
74 template < typename Val, typename Cmp >
76
78 template < typename Val >
79 struct AVLTreeNode {
80 // the neighbors in our AVL tree
81 AVLTreeNode* parent{nullptr};
82 AVLTreeNode* left_child{nullptr};
83 AVLTreeNode* right_child{nullptr};
84
85 // the height of the node in the AVL tree
86 int height{1};
87
88 // the element to be stored into the node
89 Val value;
90
91 // a class to enabling emplacing values in AVLNodes
92 enum class Emplace { EMPLACE };
93
94 explicit AVLTreeNode(const Val& val);
95
96 explicit AVLTreeNode(Val&& val) noexcept;
97
98 template < typename... Args >
99 explicit AVLTreeNode(const Emplace& emplace, Args&&... args);
100
101 AVLTreeNode(const AVLTreeNode< Val >& from);
102
103 AVLTreeNode(AVLTreeNode< Val >&& from) noexcept;
104
105 ~AVLTreeNode();
106
107 // two nodes are equal if and only if they contain the same value
108 bool operator==(const AVLTreeNode< Val >& from) const;
109 };
110
112 template < typename Val >
113 std::ostream& operator<<(std::ostream& stream, const AVLTreeNode< Val >& node);
114
116 template < typename Val >
117 class HashFunc< AVLTreeNode< Val > >: public HashFunc< Val > {
118 public:
124 static Size castToSize(const AVLTreeNode< Val >& key);
125
127
128 private: // best attempt to get rid of overloaded virtual warnings
129 using HashFunc< Val >::operator();
130
131 public:
132 INLINE Size operator()(const AVLTreeNode< Val >& key) const;
133 };
134
135#endif // DOXYGEN_SHOULD_SKIP_THIS
136
137
148 template < typename Val, typename Cmp = std::less< Val > >
149 class AVLTree {
150 public:
153 using value_type = Val;
154 using reference = Val&;
155 using const_reference = const Val&;
156 using pointer = Val*;
157 using const_pointer = const Val*;
162 using AVLNode = AVLTreeNode< Val >;
164
165 // ============================================================================
167 // ============================================================================
169
177 explicit AVLTree(const Cmp& compare = Cmp());
178
186 explicit AVLTree(std::initializer_list< Val > list);
187
193
198 AVLTree(AVLTree< Val, Cmp >&& from) noexcept;
199
204
206
207 // ============================================================================
209 // ============================================================================
211
220
228
230
231
232 // ============================================================================
234 // ============================================================================
236
241 Size size() const noexcept;
242
247 bool empty() const noexcept;
248
254 bool contains(const value_type& val) const;
255
261 bool exists(const value_type& val) const;
262
264
265 const value_type& highestValue() const;
266
268
269 const value_type& lowestValue() const;
270
272 const value_type& insert(const value_type& val);
273
276
278 template < typename... Args >
279 const value_type& emplace(Args&&... args);
280
282
287 void erase(const value_type& val);
288
290
296 void erase(iterator_safe& iter);
297
299
306
308 void clear();
309
313 std::string toString() const;
314
316
317 // ============================================================================
319 // ============================================================================
321
324
326 constexpr const iterator& end() const;
327
330
332 constexpr const reverse_iterator& rend() const;
333
336
338 constexpr const iterator_safe& endSafe() const;
339
342
344 constexpr const reverse_iterator_safe& rendSafe() const;
345
347
348 protected:
351
354
357
360
362 bool owns_nodes_{true};
363
366
368 std::vector< iterator_safe* > safe_iterators_;
369
370
372 AVLNode* lowestNode_() const noexcept;
373
375 AVLNode* highestNode_() const noexcept;
376
379
382
385
387
396
398 void erase_(AVLNode* node);
399
402
405
408
410
415 static AVLNode* copySubtree_(const AVLNode* from_node, AVLNode* new_parent);
416
418 static void deleteSubtree_(AVLNode* subtree_root_node);
419
425 };
426
437 template < typename Val, typename Cmp = std::less< Val > >
439 public:
442 using iterator_category = std::bidirectional_iterator_tag;
443 using value_type = Val;
447 using const_pointer = const value_type*;
449
450
451 // ============================================================================
453 // ============================================================================
455
462 explicit AVLTreeIterator(const AVLTree< Val, Cmp >& tree, const bool begin = true) noexcept;
463
464#ifndef DOXYGEN_SHOULD_SKIP_THIS
465 // constructor for the static end iterator
466 // only AVLTree.cpp should use this constructor
467 explicit consteval AVLTreeIterator(StaticInitializer init) noexcept {}
468#endif // DOXYGEN_SHOULD_SKIP_THIS
469
472
475
478
480
481
482 // ============================================================================
484 // ============================================================================
486
488 AVLTreeIterator< Val, Cmp >& operator=(const AVLTreeIterator< Val, Cmp >& from) noexcept;
489
491 AVLTreeIterator< Val, Cmp >& operator=(AVLTreeIterator< Val, Cmp >&& from) noexcept;
492
494 bool operator==(const AVLTreeIterator< Val, Cmp >& from) const;
495
497 bool operator!=(const AVLTreeIterator< Val, Cmp >& from) const;
498
500
502 AVLTreeIterator< Val, Cmp >& operator++() noexcept;
503
505
507 AVLTreeIterator< Val, Cmp >& operator+=(const Size k) noexcept;
508
510
512 AVLTreeIterator< Val, Cmp >& operator--() noexcept;
513
515
517 AVLTreeIterator< Val, Cmp >& operator-=(const Size k) noexcept;
518
525 const_reference operator*() const;
526
528
529
530 protected:
532 using AVLNode = AVLTreeNode< Val >;
533
535 AVLTree< Val, Cmp >* tree_{nullptr};
536
538 AVLNode* node_{nullptr};
539
542
545
546
548 AVLNode* nextNode_(AVLNode* node) const noexcept;
549
551 AVLNode* precedingNode_(AVLNode* node) const noexcept;
552
554 void unregisterTree_() noexcept;
555
557 void pointToEndRend_() noexcept;
558
559
562 };
563
574 template < typename Val, typename Cmp = std::less< Val > >
575 class AVLTreeIteratorSafe: protected AVLTreeIterator< Val, Cmp > {
576 public:
579 using iterator_category = std::bidirectional_iterator_tag;
580 using value_type = Val;
584 using const_pointer = const value_type*;
586
587
588 // ============================================================================
590 // ============================================================================
592
599 explicit AVLTreeIteratorSafe(AVLTree< Val, Cmp >& tree, const bool begin = true);
600
601#ifndef DOXYGEN_SHOULD_SKIP_THIS
602 // constructor for the static endSafe iterator
603 // only AVLTree.cpp should use this constructor
604 explicit consteval AVLTreeIteratorSafe(StaticInitializer init) noexcept :
606#endif // DOXYGEN_SHOULD_SKIP_THIS
607
610
613
616
618
619 // ============================================================================
621 // ============================================================================
623
625 AVLTreeIteratorSafe< Val, Cmp >& operator=(const AVLTreeIteratorSafe< Val, Cmp >& from);
626
628 AVLTreeIteratorSafe< Val, Cmp >& operator=(AVLTreeIteratorSafe< Val, Cmp >&& from);
629
631 bool operator==(const AVLTreeIteratorSafe< Val, Cmp >& from) const;
632
634 bool operator!=(const AVLTreeIteratorSafe< Val, Cmp >& from) const;
635
637
639 AVLTreeIteratorSafe< Val, Cmp >& operator++() noexcept;
640
642
644 AVLTreeIteratorSafe< Val, Cmp >& operator+=(const Size k) noexcept;
645
647
649 AVLTreeIteratorSafe< Val, Cmp >& operator--() noexcept;
650
652
654 AVLTreeIteratorSafe< Val, Cmp >& operator-=(const Size k) noexcept;
655
662 using AVLTreeIterator< Val, Cmp >::operator*;
663
665
666
667 protected:
670 };
671
682 template < typename Val, typename Cmp = std::less< Val > >
683 class AVLTreeReverseIterator: protected AVLTreeIterator< Val, Cmp > {
684 public:
687 using iterator_category = std::bidirectional_iterator_tag;
688 using value_type = Val;
692 using const_pointer = const value_type*;
694
695
696 // ============================================================================
698 // ============================================================================
700
708 const bool rbegin = true) noexcept;
709
710#ifndef DOXYGEN_SHOULD_SKIP_THIS
711 // constructor for the static rend iterator
712 // only AVLTree.cpp should use this constructor
713 explicit consteval AVLTreeReverseIterator(StaticInitializer init) noexcept :
715#endif // DOXYGEN_SHOULD_SKIP_THIS
716
719
722
725
727
728 // ============================================================================
730 // ============================================================================
732
735 operator=(const AVLTreeReverseIterator< Val, Cmp >& from) noexcept;
736
739 operator=(AVLTreeReverseIterator< Val, Cmp >&& from) noexcept;
740
742 bool operator==(const AVLTreeReverseIterator< Val, Cmp >& from) const;
743
745 bool operator!=(const AVLTreeReverseIterator< Val, Cmp >& from) const;
746
748
750 AVLTreeReverseIterator< Val, Cmp >& operator++() noexcept;
751
753
755 AVLTreeReverseIterator< Val, Cmp >& operator+=(const Size k) noexcept;
756
758
760 AVLTreeReverseIterator< Val, Cmp >& operator--() noexcept;
761
763
765 AVLTreeReverseIterator< Val, Cmp >& operator-=(const Size k) noexcept;
766
773 using AVLTreeIterator< Val, Cmp >::operator*;
774
776
777
778 protected:
781 };
782
793 template < typename Val, typename Cmp = std::less< Val > >
795 public:
798 using iterator_category = std::bidirectional_iterator_tag;
799 using value_type = Val;
803 using const_pointer = const value_type*;
805
806
807 // ============================================================================
809 // ============================================================================
811
818 explicit AVLTreeReverseIteratorSafe(AVLTree< Val, Cmp >& tree, const bool rbegin = true);
819
820#ifndef DOXYGEN_SHOULD_SKIP_THIS
821 // constructor for the static rendSafe iterator
822 // only AVLTree.cpp should use this constructor
823 explicit consteval AVLTreeReverseIteratorSafe(StaticInitializer init) noexcept :
825#endif // DOXYGEN_SHOULD_SKIP_THIS
826
829
832
835
837
838 // ============================================================================
840 // ============================================================================
842
845 operator=(const AVLTreeReverseIteratorSafe< Val, Cmp >& from);
846
849 operator=(AVLTreeReverseIteratorSafe< Val, Cmp >&& from);
850
852 bool operator==(const AVLTreeReverseIteratorSafe< Val, Cmp >& from) const;
853
855 bool operator!=(const AVLTreeReverseIteratorSafe< Val, Cmp >& from) const;
856
858
860 AVLTreeReverseIteratorSafe< Val, Cmp >& operator++() noexcept;
861
863
865 AVLTreeReverseIteratorSafe< Val, Cmp >& operator+=(const Size k) noexcept;
866
868
870 AVLTreeReverseIteratorSafe< Val, Cmp >& operator--() noexcept;
871
873
875 AVLTreeReverseIteratorSafe< Val, Cmp >& operator-=(const Size k) noexcept;
876
883 using AVLTreeIteratorSafe< Val, Cmp >::operator*;
884
886
887 protected:
890 };
891
893 template < typename Val, typename Cmp >
894 std::ostream& operator<<(std::ostream& stream, const AVLTree< Val, Cmp >& tree);
895
896
897#ifndef DOXYGEN_SHOULD_SKIP_THIS
898 // _static_AVLTree_end_ is a 'constant' iterator initialized at compile time
899 // that represents the end iterators for all AVL trees (whatever their
900 // type). This global variable avoids creating the same iterators within every
901 // AVL tree instance (this would be quite inefficient as end is precisely
902 // identical for all AVL trees). The same hold for reverse and safe end iterators.
903 // The type of _AVLTree_end_ is a pointer to void because C++ allows
904 // pointers to void to be cast into pointers to other types (and conversely).
905 // This avoids the painful strict-aliasing rule warning
906 extern const AVLTreeIterator< int, std::less< int > > _static_AVLTree_end_;
907 extern const AVLTreeReverseIterator< int, std::less< int > > _static_AVLTree_rend_;
908 extern const AVLTreeIteratorSafe< int, std::less< int > > _static_AVLTree_end_safe_;
909 extern const AVLTreeReverseIteratorSafe< int, std::less< int > > _static_AVLTree_rend_safe_;
910
911 inline constexpr void* const _AVLTree_end_ = (void* const)&_static_AVLTree_end_;
912 inline constexpr void* const _AVLTree_rend_ = (void* const)&_static_AVLTree_rend_;
913 inline constexpr void* const _AVLTree_end_safe_ = (void* const)&_static_AVLTree_end_safe_;
914 inline constexpr void* const _AVLTree_rend_safe_ = (void* const)&_static_AVLTree_rend_safe_;
915#endif // DOXYGEN_SHOULD_SKIP_THIS
916
917
918} // namespace gum
919
920// always include the implementation of the templates
922
923#endif // GUM_AVL_TREE_H
AVL binary search tree safe (w.r.t.
Definition AVLTree.h:575
AVLTreeIteratorSafe(AVLTree< Val, Cmp > &tree, const bool begin=true)
constructor for begin safe iterators
AVLTreeIteratorSafe(const AVLTreeIteratorSafe< Val, Cmp > &from)
copy constructor
const value_type & const_reference
Definition AVLTree.h:582
const value_type * const_pointer
Definition AVLTree.h:584
AVLTreeIteratorSafe(AVLTreeIteratorSafe< Val, Cmp > &&from)
move constructor
std::bidirectional_iterator_tag iterator_category
Definition AVLTree.h:579
~AVLTreeIteratorSafe() noexcept
destructor
AVL binary search tree iterator.
Definition AVLTree.h:438
AVLTreeNode< Val > AVLNode
Definition AVLTree.h:532
AVLTree< Val, Cmp > * tree_
Definition AVLTree.h:535
AVLNode * precedingNode_(AVLNode *node) const noexcept
computes the node to go to when applying operator--
const value_type & const_reference
Definition AVLTree.h:445
AVLTreeIterator(AVLTreeIterator< Val, Cmp > &&from) noexcept
move constructor
void unregisterTree_() noexcept
make the iterator point to nothing
~AVLTreeIterator() noexcept
destructor
AVLTreeIterator(const AVLTree< Val, Cmp > &tree, const bool begin=true) noexcept
constructor for begin iterators
const value_type * const_pointer
Definition AVLTree.h:447
AVLTreeIterator(const AVLTreeIterator< Val, Cmp > &from) noexcept
copy constructor
AVLNode * nextNode_(AVLNode *node) const noexcept
computes the node to go to when applying operator++
std::bidirectional_iterator_tag iterator_category
Definition AVLTree.h:442
AVL binary search tree safe (w.r.t.
Definition AVLTree.h:794
AVLTreeReverseIteratorSafe(AVLTreeReverseIteratorSafe< Val, Cmp > &&from)
move constructor
AVLTreeReverseIteratorSafe(AVLTree< Val, Cmp > &tree, const bool rbegin=true)
constructor for rbegin safe iterators
~AVLTreeReverseIteratorSafe() noexcept
destructor
AVLTreeReverseIteratorSafe(const AVLTreeReverseIteratorSafe< Val, Cmp > &from)
copy constructor
std::bidirectional_iterator_tag iterator_category
Definition AVLTree.h:798
AVL binary search tree reverse iterator.
Definition AVLTree.h:683
AVLTreeReverseIterator(AVLTreeReverseIterator< Val, Cmp > &&from) noexcept
move constructor
AVLTreeReverseIterator(const AVLTreeReverseIterator< Val, Cmp > &from) noexcept
copy constructor
std::bidirectional_iterator_tag iterator_category
Definition AVLTree.h:687
~AVLTreeReverseIterator() noexcept
destructor
AVLTreeReverseIterator(const AVLTree< Val, Cmp > &tree, const bool rbegin=true) noexcept
constructor for rbegin iterators
AVL binary search tree.
Definition AVLTree.h:149
AVLNode * leftRotation_(AVLNode *node_p)
rotate the subtree rooted at p to the left
AVLTreeIteratorSafe< Val, Cmp > iterator_safe
Types for STL compliance.
Definition AVLTree.h:159
AVLTreeReverseIteratorSafe< Val, Cmp > reverse_iterator_safe
Types for STL compliance.
Definition AVLTree.h:161
AVLTree(AVLTree< Val, Cmp > &&from) noexcept
Move constructor.
AVLTreeIterator< Val, Cmp > iterator
Types for STL compliance.
Definition AVLTree.h:158
AVLTree(const Cmp &compare=Cmp())
Basic constructor.
const value_type & insert_(AVLNode *node)
insert a node into the tree
std::vector< iterator_safe * > safe_iterators_
The list of safe iterators and reverse iterators used by the AVL tree.
Definition AVLTree.h:368
void clear()
remove all the elements in the tree
~AVLTree()
Class destructor.
AVLNode * rightRotation_(AVLNode *node_q)
rotate the subtree rooted at q to the right
AVLTree(std::initializer_list< Val > list)
Initializer list constructor.
void erase_(AVLNode *node)
remove a node from the tree and free memory
void removeFromSafeList_(iterator_safe *iter)
unregister a safe iterator
bool contains(const value_type &val) const
Indicates whether the tree contains a given value.
AVLNode * highest_node_
the node containing the highest element
Definition AVLTree.h:356
Val value_type
Types for STL compliance.
Definition AVLTree.h:153
AVLNode * removeNodeFromTree_(AVLNode *node)
remove a node from the tree and returns the node that was actually removed
const value_type & highestValue() const
returns the max element (w.r.t. Cmp) in the tree
AVLNode * lowestNode_() const noexcept
returns the node containing the lowest element of the tree
AVLTreeNode< Val > AVLNode
Types for STL compliance.
Definition AVLTree.h:162
const Val * const_pointer
Types for STL compliance.
Definition AVLTree.h:157
bool empty() const noexcept
Indicates whether the tree is empty.
AVLNode * highestNode_() const noexcept
returns the node containing the highest element of the tree
AVLTreeReverseIterator< Val, Cmp > reverse_iterator
Types for STL compliance.
Definition AVLTree.h:160
const value_type & emplace(Args &&... args)
emplace a new element into the tree
iterator begin() const
returns a new iterator pointing to the minimal element of the tree
static AVLNode * copySubtree_(const AVLNode *from_node, AVLNode *new_parent)
copies recursively a subtree of the AVL tree
Val & reference
Types for STL compliance.
Definition AVLTree.h:154
AVLTree< Val, Cmp > & operator=(const AVLTree< Val, Cmp > &from)
Copy operator.
void erase(const value_type &val)
remove an element from the tree
bool exists(const value_type &val) const
Alias of contains: indicates whether the tree contains a given value.
bool owns_nodes_
indicates whether the tree owns its nodes. If not, it won't delete them
Definition AVLTree.h:362
AVLNode * root_node_
the root of the AVL tree
Definition AVLTree.h:350
constexpr const iterator_safe & endSafe() const
returns a safe iterator pointing just after the maximal element
Size size() const noexcept
Returns the number of elements in the tree.
iterator_safe beginSafe()
returns a new safe iterator pointing to the minimal element of the tree
void rebalanceTree_(AVLNode *node)
rebalance the tree moving up recursively from a given node
AVLTree(const AVLTree< Val, Cmp > &from)
Copy constructor.
constexpr const reverse_iterator & rend() const
returns an iterator pointing just before the minimal element
std::string toString() const
returns a string with the content of the tree, order from the lowest to the highest element
const value_type & insert(const value_type &val)
adds (by copy) a new element into the tree
static void deleteSubtree_(AVLNode *subtree_root_node)
deletes recursively a subtree of the AVL tree
void insertIntoSafeList_(iterator_safe *iter)
register a new safe iterator
Val * pointer
Types for STL compliance.
Definition AVLTree.h:156
reverse_iterator_safe rbeginSafe()
returns a safe iterator pointing to the maximal element of the tree
const value_type & lowestValue() const
returns the min element (w.r.t. Cmp) in the tree
constexpr const reverse_iterator_safe & rendSafe() const
returns a safe iterator pointing just before the minimal element
AVLTree< Val, Cmp > & operator=(AVLTree< Val, Cmp > &&from)
Move operator.
reverse_iterator rbegin() const
returns a new iterator pointing to the maximal element of the tree
const Val & const_reference
Types for STL compliance.
Definition AVLTree.h:155
AVLNode * lowest_node_
the node containing the lowest element
Definition AVLTree.h:353
Cmp cmp_
the comparison function
Definition AVLTree.h:365
constexpr const iterator & end() const
returns an iterator pointing just after the maximal element
Size nb_elements_
the number of elements in the tree
Definition AVLTree.h:359
This class should be useless as only its specializations should be used.
Definition hashFunc.h:492
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Classes providing basic hash functions for hash tables.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
std::ostream & operator<<(std::ostream &stream, const AVLTree< Val, Cmp > &tree)
display the content of a tree
STL namespace.
Data types to enable creating static variables at compile time.
bool operator==(const TiXmlString &a, const TiXmlString &b)
Definition tinystr.h:243