54#include <lal/detail/macros/basic_convert.hpp>
93 {
return not (*
this == f); }
122 assert(
m_root !=
nullptr);
139 template <
bool use_counter>
142 m_root = remove_rightmost<use_counter>(
m_root,
nullptr, freqs);
155 template <
bool use_counter>
158 m_root = remove_leftmost<use_counter>(
m_root,
nullptr, freqs);
170 assert(
m_root !=
nullptr);
175 while (n->
left !=
nullptr) {
177 freqs.num_nodes_larger += 1 + n->
right_size();
183 return {n->
key, freqs};
195 while (n !=
nullptr) {
219 template <
typename U>
234 template <
bool use_counter>
251 template <
typename U>
253 using elem_t =
typename std::remove_reference_t<U>::value_type;
254 static constexpr bool rvalue = std::is_same_v<std::vector<elem_t>, U>;
257 assert(std::is_sorted(v.begin(), v.end()));
261 if (v.size() == 0) {
return; }
266 if constexpr (rvalue) {
267 return insert(
nullptr,
m_root, std::forward<T>(v[0]), dummy);
278 _make_tree(std::forward<U>(v), 0, v.size() - 1,
nullptr,
'0');
291 assert(r !=
nullptr);
297 while (lmost->
left !=
nullptr) { lmost = lmost->
left; }
301 while (lmost->
parent !=
nullptr) {
337#if defined __LAL_INSPECT
339 bool sanity_check() const noexcept {
340 return sanity_check(
m_root);
345 void print_tree() const noexcept {
482 else if (
side ==
'r') {
487 if (n ==
nullptr) {
return; }
505 if (n ==
nullptr) {
return; }
522 assert(n !=
nullptr);
529 assert(L !=
nullptr);
535 if (n->side ==
'r') { P->right = L; }
536 else if (n->side ==
'l') { P->left = L; }
571 assert(n !=
nullptr);
580 else if (n->side ==
'l') { n->
parent->
left = R; }
651 if (n ==
nullptr) {
return nullptr; }
653 assert(std::abs(n->balance_factor) <= 2);
656 if (std::abs(n->balance_factor) <= 1) {
return n; }
658 n->balance_factor == -2 ?
675 template <
typename U>
684 while (n !=
nullptr and (not (x == n->key))) {
688 freqs.counter_larger += n->node_counter + n->right_counter();
689 freqs.num_nodes_larger += 1 + n->right_size();
700 const bool create_a_new_node = (n ==
nullptr);
701 if (create_a_new_node) {
704 n->key = std::forward<U>(x);
705 n->left = n->right =
nullptr;
708 if (side ==
'l') { p->left = n; }
709 else if (side ==
'r') { p->right = n; }
710 n->tree_size = n->node_counter = n->tree_counter = 1;
712 n->balance_factor = 0;
713 freqs.counter_equal = 1;
720 n->node_counter += 1;
721 n->tree_counter += 1;
724 freqs.counter_equal = n->node_counter;
725 freqs.counter_larger += n->right_counter();
726 freqs.num_nodes_larger += n->right_size();
734 assert(n !=
nullptr);
739 if (create_a_new_node) {
743 while (p->parent !=
nullptr) {
752 while (p->parent !=
nullptr) {
777 template <
bool use_counter_to_remove,
bool move_in_leftmost>
780 freqs.counter_equal = n->node_counter;
781 if constexpr (move_in_leftmost) {
782 freqs.counter_larger += n->right_counter();
783 freqs.num_nodes_larger += n->right_size();
786 bool delete_n =
false;
787 if constexpr (not use_counter_to_remove) {
793 delete_n = n->node_counter == 0;
797 k->node_counter = n->node_counter;
798 if (delete_n) { k->key = std::move(n->key); }
799 else { k->key = n->key; }
815 template <
bool use_counter_to_remove>
820 if (n ==
nullptr) {
return nullptr; }
822 assert(n !=
nullptr);
825 const auto original = n;
828 if (n->left ==
nullptr) {
829 const auto delete_n =
830 delete_after_move<use_counter_to_remove, true>(n, k, freqs);
832 if (not delete_n) {
return original; }
834 if (n->parent ==
nullptr) {
835 const auto l = n->right;
841 n->replace_with(n->right);
847 while (n->left !=
nullptr) {
848 freqs.counter_larger += n->node_counter + n->right_counter();
849 freqs.num_nodes_larger += 1 + n->right_size();
856 const auto delete_n =
857 delete_after_move<use_counter_to_remove, true>(n, k, freqs);
860 n->replace_with(n->right);
865 while (p != original) {
884 template <
bool use_counter_to_remove>
889 if (n ==
nullptr) {
return nullptr; }
892 assert(n !=
nullptr);
895 const auto original = n;
898 if (n->right ==
nullptr) {
899 const auto delete_n =
900 delete_after_move<use_counter_to_remove, false>(n, k, freqs);
902 if (not delete_n) {
return original; }
904 if (n->parent ==
nullptr) {
905 const auto l = n->left;
911 n->replace_with(n->left);
917 while (n->right !=
nullptr) { n = n->right; }
922 const auto delete_n =
923 delete_after_move<use_counter_to_remove, false>(n, k, freqs);
926 n->replace_with(n->left);
931 while (p != original) {
949 template <
bool use_counter_to_remove>
956 freqs.counter_equal = 0;
962 freqs.counter_larger += n->
node_counter + n->right_counter();
963 freqs.num_nodes_larger += 1 + n->right_size();
966 n->left = remove<use_counter_to_remove>(n->left, x, freqs);
974 n->right = remove<use_counter_to_remove>(n->right, x, freqs);
986 freqs.counter_equal = n->node_counter;
987 freqs.counter_larger += n->right_counter();
988 freqs.num_nodes_larger += n->right_size();
990 bool completely_remove =
false;
991 if constexpr (not use_counter_to_remove) {
993 completely_remove =
true;
997 assert(n->tree_counter > 0);
998 assert(n->node_counter > 0);
1001 n->tree_counter -= 1;
1002 n->node_counter -= 1;
1003 completely_remove = n->node_counter == 0;
1006 if (completely_remove) {
1010 if (L ==
nullptr and R ==
nullptr) {
1015 if (L !=
nullptr and R ==
nullptr) {
1021 if (L ==
nullptr and R !=
nullptr) {
1036 n->left = remove_rightmost<false>(L, n, dummy);
1039 n->right = remove_leftmost<false>(R, n, dummy);
1061 assert(T1 !=
nullptr);
1062 assert(T2 !=
nullptr);
1063 assert(T1->tree_size > 1 and T2->tree_size > 1);
1072 T2 = remove_leftmost<false>(T2, x, dummy);
1076 const std::size_t h = T2->height;
1078 std::size_t hp = v->
height;
1079 while (hp > h + 1 and v !=
nullptr) {
1085 assert(v !=
nullptr);
1111 while (u->
parent !=
nullptr) {
1117 assert(u !=
nullptr);
1135 assert(T1 !=
nullptr);
1136 assert(T2 !=
nullptr);
1137 assert(T1->tree_size > 1 and T2->tree_size > 1);
1146 T1 = remove_rightmost<false>(T1, x, dummy);
1152 const std::size_t h = T1->height;
1154 std::size_t hp = v->
height;
1155 while (hp > h + 1 and v !=
nullptr) {
1160 assert(v !=
nullptr);
1186 while (u->
parent !=
nullptr) {
1192 assert(u !=
nullptr);
1214 template <
typename U>
1216 (U&& v, std::size_t l, std::size_t r,
tree_node *p,
char s)
1219 using elem_t =
typename std::remove_reference_t<U>::value_type;
1220 static constexpr bool rvalue = std::is_same_v<std::vector<elem_t>, U>;
1223 const std::size_t m = (l + r)/2;
1226 if constexpr (rvalue) {
1227 n->
key = std::forward<T>(v[m]);
1236 n->
left = (l + 1 > m ?
1237 nullptr :
_make_tree(std::forward<U>(v), l, m - 1, n,
'l'));
1238 n->
right = (m + 1 > r ?
1239 nullptr :
_make_tree(std::forward<U>(v), m + 1, r, n,
'r'));
1249#if defined __LAL_INSPECT
1250 std::size_t exhaustive_size(tree_node *n)
const noexcept {
1251 if (n ==
nullptr) {
return 0; }
1252 return 1 + exhaustive_size(n->right) + exhaustive_size(n->left);
1254 std::size_t exhaustive_occurrences(tree_node *n)
const noexcept {
1255 if (n ==
nullptr) {
return 0; }
1256 return n->node_counter +
1257 exhaustive_occurrences(n->right) +
1258 exhaustive_occurrences(n->left);
1260 std::size_t exhaustive_height(tree_node *n)
const noexcept {
1261 if (n ==
nullptr) {
return 0; }
1262 if (n->left ==
nullptr and n->right ==
nullptr) {
return 0; }
1263 const auto height_left = exhaustive_height(n->left);
1264 const auto height_right = exhaustive_height(n->right);
1265 return 1 + std::max(height_left, height_right);
1268 bool all_smaller_than(tree_node *n,
const T& x)
const noexcept {
1269 if (n ==
nullptr) {
return true; }
1270 if (n->key > x) {
return false; }
1271 return all_smaller_than(n->left, x) and all_smaller_than(n->right, x);
1273 bool all_greater_than(tree_node *n,
const T& x)
const noexcept {
1274 if (n ==
nullptr) {
return true; }
1275 if (n->key < x) {
return false; }
1276 return all_greater_than(n->left, x) and all_greater_than(n->right, x);
1278 bool check_relations(tree_node *n)
const noexcept
1280 if (n ==
nullptr) {
return true; }
1281 const bool smaller_left = all_smaller_than(n->left, n->key);
1282 const bool greater_right = all_greater_than(n->right, n->key);
1283 if (not smaller_left or not greater_right) {
return false; }
1284 return check_relations(n->left) and check_relations(n->right);
1286 bool sanity_check(tree_node *n) const noexcept {
1287 if (n ==
nullptr) {
return true; }
1289 if (not check_relations(n)) {
1291 <<
"Elements incorrectly placed in the tree.\n"
1292 <<
" n->key= " << n->key <<
'\n';
1296 if (std::abs(n->balance_factor) >= 2) {
1298 <<
"Incorrect balance factor.\n"
1299 <<
" n->key= " << n->key <<
'\n'
1300 <<
" n->balance_factor= " << n->balance_factor <<
'\n';
1306 const auto my_height = exhaustive_height(n);
1307 if (my_height != n->height) {
1309 <<
"Incorrect height.\n"
1310 <<
" n->key= " << n->key <<
'\n'
1311 <<
" n->height= " << n->height <<
'\n'
1312 <<
" my_height= " << my_height <<
'\n';
1319 const auto my_size = exhaustive_size(n);
1320 if (my_size != n->tree_size) {
1322 <<
"Incorrect sizes.\n"
1323 <<
" n->key= " << n->key <<
'\n'
1324 <<
" n->tree_size= " << n->tree_size <<
'\n'
1325 <<
" my_size= " << my_size <<
'\n';
1331 const auto my_size = exhaustive_size(n->left);
1332 if (my_size != n->left_size()) {
1334 <<
"Incorrect sizes.\n"
1335 <<
" n->key= " << n->key <<
'\n'
1336 <<
" n->left_size()= " << n->left_size() <<
'\n'
1337 <<
" my_size= " << my_size <<
'\n';
1343 const auto my_size = exhaustive_size(n->right);
1344 if (my_size != n->right_size()) {
1346 <<
"Incorrect sizes.\n"
1347 <<
" n->key= " << n->key <<
'\n'
1348 <<
" n->right_size()= " << n->right_size() <<
'\n'
1349 <<
" my_size= " << my_size <<
'\n';
1356 const auto my_occurrences = exhaustive_occurrences(n);
1357 if (my_occurrences != n->tree_counter) {
1359 <<
"Incorrect occurrencess.\n"
1360 <<
" n->key= " << n->key <<
'\n'
1361 <<
" n->tree_occurrences= " << n->tree_counter <<
'\n'
1362 <<
" my_occurrences= " << my_occurrences <<
'\n';
1368 const auto my_occurrences = exhaustive_occurrences(n->left);
1369 if (my_occurrences != n->left_counter()) {
1371 <<
"Incorrect occurrencess.\n"
1372 <<
" n->key= " << n->key <<
'\n'
1373 <<
" n->left_occurrences()= " << n->left_counter() <<
'\n'
1374 <<
" my_occurrences= " << my_occurrences <<
'\n';
1380 const auto my_occurrences = exhaustive_occurrences(n->right);
1381 if (my_occurrences != n->right_counter()) {
1383 <<
"Incorrect occurrencess.\n"
1384 <<
" n->key= " << n->key <<
'\n'
1385 <<
" n->right_occurrences()= " << n->right_counter() <<
'\n'
1386 <<
" my_occurrences= " << my_occurrences <<
'\n';
1391 if (n->left !=
nullptr) {
1392 if (n->left->key > n->key) {
1394 <<
"Keys do not satisfy the order requirement.\n"
1395 <<
" n->key= " << n->key <<
'\n'
1396 <<
" n->left->key= " << n->left->key <<
'\n'
1397 <<
" n->key= " << n->key <<
'\n';
1401 if (n->left->side !=
'l') {
1402 std::cerr <<
"Wrong side for left child: '" << n->left->side <<
".\n";
1407 if (n->right !=
nullptr) {
1408 if (n->right->key < n->key) {
1410 <<
"Keys do not satisfy the order requirement.\n"
1411 <<
" n->key= " << n->key <<
'\n'
1412 <<
" n->right->key= " << n->right->key
1413 <<
" n->key= " << n->key <<
'\n';
1417 if (n->right->side !=
'r') {
1418 std::cerr <<
"Wrong side for right child: '" << n->right->side <<
".\n";
1423 return sanity_check(n->left) and sanity_check(n->right);
1426 void print_tree(tree_node *n, const std::
string& tab) const noexcept {
1436 <<
", nc= " << n->node_counter
1437 <<
", s= " << n->side
1438 <<
", ls= " << n->left_size()
1439 <<
", rs= " << n->right_size()
1440 <<
", h= " << n->height
1441 <<
", ts= " << n->tree_size
1442 <<
", tc= " << n->tree_counter
1443 <<
", bf= " << n->balance_factor
1445 print_tree(n->left, tab +
"| -l-: ");
1446 print_tree(n->right, tab +
"| +r+: ");
1451template <
typename T>
1452using AVL_frequencies =
typename AVL<T>::frequencies;
Simple class that implements an AVL tree.
Definition: avl.hpp:74
tree_node * right_right_case(tree_node *n) const noexcept
Right-right imbalance case.
Definition: avl.hpp:629
tree_node * right_left_case(tree_node *n) const noexcept
Right-left imbalance case.
Definition: avl.hpp:638
bool delete_after_move(tree_node *n, tree_node *k, frequencies &freqs) const noexcept
Moves the contents of n to k, when appropriate.
Definition: avl.hpp:778
tree_node * join_taller(tree_node *T1, tree_node *T2) const noexcept
Join two AVL trees.
Definition: avl.hpp:1059
tree_node * m_root
Root of this AVL tree.
Definition: avl.hpp:500
tree_node * remove(tree_node *n, const T &x, frequencies &freqs) const noexcept
Remove an element from the tree.
Definition: avl.hpp:951
~AVL() noexcept
Destructor.
Definition: avl.hpp:98
tree_node * remove_rightmost(tree_node *n, tree_node *k, frequencies &freqs) const noexcept
Remove the rightmost node in tree rooted at n.
Definition: avl.hpp:886
tree_node * _make_tree(U &&v, std::size_t l, std::size_t r, tree_node *p, char s) const noexcept
Make an AVL tree from the elements in v.
Definition: avl.hpp:1216
tree_node * insert(tree_node *p, tree_node *n, U &&x, frequencies &freqs) const noexcept
Insert element 'x' to the tree.
Definition: avl.hpp:677
frequencies element_frequency(const T &v) const noexcept
Number of occurrences associated to a given value.
Definition: avl.hpp:191
void free_node(tree_node *n) const noexcept
Deallocates the memory of node n.
Definition: avl.hpp:504
frequencies insert(U &&v) noexcept
Insert a new value v into the tree.
Definition: avl.hpp:220
frequencies remove_largest() noexcept
Remove an element from the tree.
Definition: avl.hpp:140
std::size_t num_nodes() const noexcept
Size of the tree.
Definition: avl.hpp:327
frequencies remove(const T &v) noexcept
Remove an element from the tree.
Definition: avl.hpp:235
tree_node * left_rotation(tree_node *n) const noexcept
Performs a left-rotation at node n.
Definition: avl.hpp:569
void join_sorted_all_greater(U &&v) noexcept
Add to the tree the elements in the vector v.
Definition: avl.hpp:252
void clear() noexcept
Empties the tree.
Definition: avl.hpp:109
std::pair< const T &, frequencies > get_smallest_value() const noexcept
Find the largest value.
Definition: avl.hpp:168
tree_node * join_shorter(tree_node *T1, tree_node *T2) const noexcept
Join two AVL trees.
Definition: avl.hpp:1133
tree_node * left_left_case(tree_node *n) const noexcept
Left-left imbalance case.
Definition: avl.hpp:610
tree_node * balance(tree_node *n) const noexcept
Balance a node of the AVL tree.
Definition: avl.hpp:650
std::size_t total_elements() const noexcept
Total number of elements inserted.
Definition: avl.hpp:334
tree_node * left_right_case(tree_node *n) const noexcept
Left-right imbalance case.
Definition: avl.hpp:619
frequencies remove_smallest() noexcept
Remove an element from the tree.
Definition: avl.hpp:156
tree_node * right_rotation(tree_node *n) const noexcept
Performs a right-rotation at node n.
Definition: avl.hpp:520
std::pair< const T &, frequencies > get_largest_value() const noexcept
Finds the largest value.
Definition: avl.hpp:120
tree_node * remove_leftmost(tree_node *n, tree_node *k, frequencies &freqs) const noexcept
Remove the leftmost node in tree rooted at n.
Definition: avl.hpp:817
constexpr int64_t to_int64(const T &t) noexcept
Conversion to int64_t.
Definition: basic_convert.hpp:52
constexpr uint64_t to_uint64(const T &t) noexcept
Conversion to uint64_t.
Definition: basic_convert.hpp:57
Main namespace of the library.
Definition: basic_types.hpp:50
Frequency of a value in the tree v.
Definition: avl.hpp:77
bool operator!=(const frequencies &f) const noexcept
Different operator.
Definition: avl.hpp:92
std::size_t counter_larger
Number of occurrences of larger elements than v in the tree.
Definition: avl.hpp:81
bool operator==(const frequencies &f) const noexcept
Equality comparison.
Definition: avl.hpp:85
std::size_t num_nodes_larger
Number of nodes with a key larger than v in the tree.
Definition: avl.hpp:83
std::size_t counter_equal
Number of occurrences of v in the tree.
Definition: avl.hpp:79
Node of the tree.
Definition: avl.hpp:352
void update_height_and_balance_factor() noexcept
Calculate the height and balance factor of this node.
Definition: avl.hpp:422
T key
contents of the node
Definition: avl.hpp:354
std::size_t left_size() const noexcept
Returns the size of the left subtree.
Definition: avl.hpp:405
std::size_t right_size() const noexcept
Returns the size of the right subtree.
Definition: avl.hpp:408
tree_node * left
Pointer to the left subtree.
Definition: avl.hpp:390
void update_size() noexcept
Computes the size of the subtree rooted at this node.
Definition: avl.hpp:433
void update() noexcept
Updates information of this node.
Definition: avl.hpp:455
void update_count() noexcept
Computes the size of the subtree rooted at this node.
Definition: avl.hpp:441
std::size_t height
Maximum height of the left and right subtrees' height.
Definition: avl.hpp:378
std::size_t tree_counter
Total number of occurrences in the nodes in the subtree rooted at this node.
Definition: avl.hpp:375
std::size_t node_counter
Amount of occurrences of key.
Definition: avl.hpp:356
std::size_t right_counter() const noexcept
Returns the size of the right subtree.
Definition: avl.hpp:415
std::size_t left_counter() const noexcept
Returns the total occurrences of the left subtree.
Definition: avl.hpp:412
char side
Side of this node with respect to its parent.
Definition: avl.hpp:402
int64_t balance_factor
Balance factor of a node:
Definition: avl.hpp:385
std::size_t tree_size
Amount of nodes in the subtree rooted at this node.
Definition: avl.hpp:363
void replace_with(tree_node *n) noexcept
Replace this node with either its left or right child.
Definition: avl.hpp:477
tree_node * right
Pointer to the right subtree.
Definition: avl.hpp:392
tree_node * parent
Pointer to the parent of this node.
Definition: avl.hpp:388