53#include <lal/detail/macros/basic_convert.hpp>
92 {
return not (*
this == f); }
122 assert(
m_root !=
nullptr);
139 template <
bool use_counter>
155 template <
bool use_counter>
171 assert(
m_root !=
nullptr);
176 while (n->
left !=
nullptr) {
178 freqs.num_nodes_larger += 1 + n->
right_size();
184 return {n->
key, freqs};
196 while (n !=
nullptr) {
220 template <
typename U>
235 template <
bool use_counter>
252 template <
typename U>
254 using elem_t =
typename std::remove_reference_t<U>::value_type;
255 static constexpr bool rvalue = std::is_same_v<std::vector<elem_t>, U>;
258 assert(std::is_sorted(v.begin(), v.end()));
262 if (v.size() == 0) {
return; }
267 if constexpr (rvalue) {
268 return insert(
nullptr,
m_root, std::forward<T>(v[0]), dummy);
279 _make_tree(std::forward<U>(v), 0, v.size() - 1,
nullptr,
'0');
292 assert(r !=
nullptr);
298 while (lmost->
left !=
nullptr) { lmost = lmost->
left; }
302 while (lmost->
parent !=
nullptr) {
338#if defined __LAL_DEBUG_AVL
340 [[nodiscard]]
bool sanity_check() const noexcept {
341 return sanity_check(
m_root);
346 void print_tree() const noexcept {
483 else if (
side ==
'r') {
488 if (n ==
nullptr) {
return; }
506 if (n ==
nullptr) {
return; }
523 assert(n !=
nullptr);
530 assert(L !=
nullptr);
536 if (n->side ==
'r') { P->
right = L; }
537 else if (n->side ==
'l') { P->
left = L; }
572 assert(n !=
nullptr);
581 else if (n->side ==
'l') { n->
parent->
left = R; }
652 if (n ==
nullptr) {
return nullptr; }
654 assert(std::abs(n->balance_factor) <= 2);
657 if (std::abs(n->balance_factor) <= 1) {
return n; }
659 n->balance_factor == -2 ?
676 template <
typename U>
690 while (n !=
nullptr and (not (x == n->key))) {
694 freqs.counter_larger += n->node_counter + n->right_counter();
695 freqs.num_nodes_larger += 1 + n->right_size();
706 const bool create_a_new_node = (n ==
nullptr);
707 if (create_a_new_node) {
710 n->key = std::forward<U>(x);
711 n->left = n->right =
nullptr;
714 if (side ==
'l') { p->left = n; }
715 else if (side ==
'r') { p->right = n; }
716 n->tree_size = n->node_counter = n->tree_counter = 1;
718 n->balance_factor = 0;
719 freqs.counter_equal = 1;
726 n->node_counter += 1;
727 n->tree_counter += 1;
730 freqs.counter_equal = n->node_counter;
731 freqs.counter_larger += n->right_counter();
732 freqs.num_nodes_larger += n->right_size();
740 assert(n !=
nullptr);
745 if (create_a_new_node) {
749 while (p->parent !=
nullptr) {
758 while (p->parent !=
nullptr) {
783 template <
bool use_counter_to_remove,
bool move_in_leftmost>
788 freqs.counter_equal = n->node_counter;
789 if constexpr (move_in_leftmost) {
790 freqs.counter_larger += n->right_counter();
791 freqs.num_nodes_larger += n->right_size();
794 bool delete_n =
false;
795 if constexpr (not use_counter_to_remove) {
801 delete_n = n->node_counter == 0;
805 k->node_counter = n->node_counter;
806 if (delete_n) { k->key = std::move(n->key); }
807 else { k->key = n->key; }
823 template <
bool use_counter_to_remove>
828 if (n ==
nullptr) {
return nullptr; }
830 assert(n !=
nullptr);
833 const auto original = n;
836 if (n->left ==
nullptr) {
837 const auto delete_n =
840 if (not delete_n) {
return original; }
842 if (n->parent ==
nullptr) {
843 const auto l = n->right;
849 n->replace_with(n->right);
855 while (n->left !=
nullptr) {
856 freqs.counter_larger += n->node_counter + n->right_counter();
857 freqs.num_nodes_larger += 1 + n->right_size();
864 const auto delete_n =
868 n->replace_with(n->right);
873 while (p != original) {
892 template <
bool use_counter_to_remove>
897 if (n ==
nullptr) {
return nullptr; }
900 assert(n !=
nullptr);
903 const auto original = n;
906 if (n->right ==
nullptr) {
907 const auto delete_n =
910 if (not delete_n) {
return original; }
912 if (n->parent ==
nullptr) {
913 const auto l = n->left;
919 n->replace_with(n->left);
925 while (n->right !=
nullptr) { n = n->right; }
930 const auto delete_n =
934 n->replace_with(n->left);
939 while (p != original) {
957 template <
bool use_counter_to_remove>
964 freqs.counter_equal = 0;
970 freqs.counter_larger += n->
node_counter + n->right_counter();
971 freqs.num_nodes_larger += 1 + n->right_size();
994 freqs.counter_equal = n->node_counter;
995 freqs.counter_larger += n->right_counter();
996 freqs.num_nodes_larger += n->right_size();
998 bool completely_remove =
false;
999 if constexpr (not use_counter_to_remove) {
1001 completely_remove =
true;
1005 assert(n->tree_counter > 0);
1006 assert(n->node_counter > 0);
1009 n->tree_counter -= 1;
1010 n->node_counter -= 1;
1011 completely_remove = n->node_counter == 0;
1014 if (completely_remove) {
1018 if (L ==
nullptr and R ==
nullptr) {
1023 if (L !=
nullptr and R ==
nullptr) {
1029 if (L ==
nullptr and R !=
nullptr) {
1070 assert(T1 !=
nullptr);
1071 assert(T2 !=
nullptr);
1072 assert(T1->tree_size > 1 and T2->tree_size > 1);
1085 const std::size_t h = T2->height;
1087 std::size_t hp = v->
height;
1088 while (hp > h + 1 and v !=
nullptr) {
1094 assert(v !=
nullptr);
1120 while (u->
parent !=
nullptr) {
1126 assert(u !=
nullptr);
1145 assert(T1 !=
nullptr);
1146 assert(T2 !=
nullptr);
1147 assert(T1->tree_size > 1 and T2->tree_size > 1);
1162 const std::size_t h = T1->height;
1164 std::size_t hp = v->
height;
1165 while (hp > h + 1 and v !=
nullptr) {
1170 assert(v !=
nullptr);
1196 while (u->
parent !=
nullptr) {
1202 assert(u !=
nullptr);
1224 template <
typename U>
1226 (U&& v, std::size_t l, std::size_t r,
tree_node *p,
char s)
1229 using elem_t =
typename std::remove_reference_t<U>::value_type;
1230 static constexpr bool rvalue = std::is_same_v<std::vector<elem_t>, U>;
1233 const std::size_t m = (l + r)/2;
1236 if constexpr (rvalue) {
1237 n->
key = std::forward<T>(v[m]);
1246 n->
left = (l + 1 > m ?
1247 nullptr :
_make_tree(std::forward<U>(v), l, m - 1, n,
'l'));
1248 n->
right = (m + 1 > r ?
1249 nullptr :
_make_tree(std::forward<U>(v), m + 1, r, n,
'r'));
1259#if defined __LAL_DEBUG_AVL
1260 [[nodiscard]] std::size_t exhaustive_size(tree_node *n)
const noexcept {
1261 if (n ==
nullptr) {
return 0; }
1262 return 1 + exhaustive_size(n->right) + exhaustive_size(n->left);
1264 [[nodiscard]] std::size_t exhaustive_occurrences(tree_node *n)
const noexcept {
1265 if (n ==
nullptr) {
return 0; }
1266 return n->node_counter +
1267 exhaustive_occurrences(n->right) +
1268 exhaustive_occurrences(n->left);
1270 [[nodiscard]] std::size_t exhaustive_height(tree_node *n)
const noexcept {
1271 if (n ==
nullptr) {
return 0; }
1272 if (n->left ==
nullptr and n->right ==
nullptr) {
return 0; }
1273 const auto height_left = exhaustive_height(n->left);
1274 const auto height_right = exhaustive_height(n->right);
1275 return 1 + std::max(height_left, height_right);
1278 [[nodiscard]]
bool all_smaller_than(tree_node *n,
const T& x)
const noexcept {
1279 if (n ==
nullptr) {
return true; }
1280 if (n->key > x) {
return false; }
1281 return all_smaller_than(n->left, x) and all_smaller_than(n->right, x);
1283 [[nodiscard]]
bool all_greater_than(tree_node *n,
const T& x)
const noexcept {
1284 if (n ==
nullptr) {
return true; }
1285 if (n->key < x) {
return false; }
1286 return all_greater_than(n->left, x) and all_greater_than(n->right, x);
1288 [[nodiscard]]
bool check_relations(tree_node *n)
const noexcept
1290 if (n ==
nullptr) {
return true; }
1291 const bool smaller_left = all_smaller_than(n->left, n->key);
1292 const bool greater_right = all_greater_than(n->right, n->key);
1293 if (not smaller_left or not greater_right) {
return false; }
1294 return check_relations(n->left) and check_relations(n->right);
1296 [[nodiscard]]
bool sanity_check(tree_node *n) const noexcept {
1297 if (n ==
nullptr) {
return true; }
1299 if (not check_relations(n)) {
1301 <<
"Elements incorrectly placed in the tree.\n"
1302 <<
" n->key= " << n->key <<
'\n';
1306 if (std::abs(n->balance_factor) >= 2) {
1308 <<
"Incorrect balance factor.\n"
1309 <<
" n->key= " << n->key <<
'\n'
1310 <<
" n->balance_factor= " << n->balance_factor <<
'\n';
1316 const auto my_height = exhaustive_height(n);
1317 if (my_height != n->height) {
1319 <<
"Incorrect height.\n"
1320 <<
" n->key= " << n->key <<
'\n'
1321 <<
" n->height= " << n->height <<
'\n'
1322 <<
" my_height= " << my_height <<
'\n';
1329 const auto my_size = exhaustive_size(n);
1330 if (my_size != n->tree_size) {
1332 <<
"Incorrect sizes.\n"
1333 <<
" n->key= " << n->key <<
'\n'
1334 <<
" n->tree_size= " << n->tree_size <<
'\n'
1335 <<
" my_size= " << my_size <<
'\n';
1341 const auto my_size = exhaustive_size(n->left);
1342 if (my_size != n->left_size()) {
1344 <<
"Incorrect sizes.\n"
1345 <<
" n->key= " << n->key <<
'\n'
1346 <<
" n->left_size()= " << n->left_size() <<
'\n'
1347 <<
" my_size= " << my_size <<
'\n';
1353 const auto my_size = exhaustive_size(n->right);
1354 if (my_size != n->right_size()) {
1356 <<
"Incorrect sizes.\n"
1357 <<
" n->key= " << n->key <<
'\n'
1358 <<
" n->right_size()= " << n->right_size() <<
'\n'
1359 <<
" my_size= " << my_size <<
'\n';
1366 const auto my_occurrences = exhaustive_occurrences(n);
1367 if (my_occurrences != n->tree_counter) {
1369 <<
"Incorrect occurrencess.\n"
1370 <<
" n->key= " << n->key <<
'\n'
1371 <<
" n->tree_occurrences= " << n->tree_counter <<
'\n'
1372 <<
" my_occurrences= " << my_occurrences <<
'\n';
1378 const auto my_occurrences = exhaustive_occurrences(n->left);
1379 if (my_occurrences != n->left_counter()) {
1381 <<
"Incorrect occurrencess.\n"
1382 <<
" n->key= " << n->key <<
'\n'
1383 <<
" n->left_occurrences()= " << n->left_counter() <<
'\n'
1384 <<
" my_occurrences= " << my_occurrences <<
'\n';
1390 const auto my_occurrences = exhaustive_occurrences(n->right);
1391 if (my_occurrences != n->right_counter()) {
1393 <<
"Incorrect occurrencess.\n"
1394 <<
" n->key= " << n->key <<
'\n'
1395 <<
" n->right_occurrences()= " << n->right_counter() <<
'\n'
1396 <<
" my_occurrences= " << my_occurrences <<
'\n';
1401 if (n->left !=
nullptr) {
1402 if (n->left->key > n->key) {
1404 <<
"Keys do not satisfy the order requirement.\n"
1405 <<
" n->key= " << n->key <<
'\n'
1406 <<
" n->left->key= " << n->left->key <<
'\n'
1407 <<
" n->key= " << n->key <<
'\n';
1411 if (n->left->side !=
'l') {
1412 std::cerr <<
"Wrong side for left child: '" << n->left->side <<
".\n";
1417 if (n->right !=
nullptr) {
1418 if (n->right->key < n->key) {
1420 <<
"Keys do not satisfy the order requirement.\n"
1421 <<
" n->key= " << n->key <<
'\n'
1422 <<
" n->right->key= " << n->right->key
1423 <<
" n->key= " << n->key <<
'\n';
1427 if (n->right->side !=
'r') {
1428 std::cerr <<
"Wrong side for right child: '" << n->right->side <<
".\n";
1433 return sanity_check(n->left) and sanity_check(n->right);
1436 void print_tree(tree_node *n, const std::
string& tab) const noexcept {
1446 <<
", nc= " << n->node_counter
1447 <<
", s= " << n->side
1448 <<
", ls= " << n->left_size()
1449 <<
", rs= " << n->right_size()
1450 <<
", h= " << n->height
1451 <<
", ts= " << n->tree_size
1452 <<
", tc= " << n->tree_counter
1453 <<
", bf= " << n->balance_factor
1455 print_tree(n->left, tab +
"| -l-: ");
1456 print_tree(n->right, tab +
"| +r+: ");
1461template <
typename T>
1462using AVL_frequencies =
typename AVL<T>::frequencies;
Simple class that implements an AVL tree.
Definition avl.hpp:73
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:785
tree_node * left_right_case(tree_node *const n) const noexcept
Left-right imbalance case.
Definition avl.hpp:620
tree_node * join_taller(tree_node *T1, tree_node *T2) const noexcept
Join two AVL trees.
Definition avl.hpp:1066
tree_node * m_root
Root of this AVL tree.
Definition avl.hpp:501
tree_node * remove(tree_node *n, const T &x, frequencies &freqs) const noexcept
Remove an element from the tree.
Definition avl.hpp:959
~AVL() noexcept
Destructor.
Definition avl.hpp:97
tree_node * left_rotation(tree_node *const n) const noexcept
Performs a left-rotation at node n.
Definition avl.hpp:570
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:894
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:1226
tree_node * insert(tree_node *p, tree_node *n, U &&x, frequencies &freqs) const noexcept
Insert element 'x' to the tree.
Definition avl.hpp:678
frequencies element_frequency(const T &v) const noexcept
Number of occurrences associated to a given value.
Definition avl.hpp:192
tree_node * balance(tree_node *const n) const noexcept
Balance a node of the AVL tree.
Definition avl.hpp:651
frequencies insert(U &&v) noexcept
Insert a new value v into the tree.
Definition avl.hpp:221
tree_node * right_rotation(tree_node *const n) const noexcept
Performs a right-rotation at node n.
Definition avl.hpp:521
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:328
frequencies remove(const T &v) noexcept
Remove an element from the tree.
Definition avl.hpp:236
void free_node(tree_node *const n) const noexcept
Deallocates the memory of node n.
Definition avl.hpp:505
tree_node * left_left_case(tree_node *const n) const noexcept
Left-left imbalance case.
Definition avl.hpp:611
void join_sorted_all_greater(U &&v) noexcept
Add to the tree the elements in the vector v.
Definition avl.hpp:253
tree_node * right_left_case(tree_node *const n) const noexcept
Right-left imbalance case.
Definition avl.hpp:639
void clear() noexcept
Empties the tree.
Definition avl.hpp:108
std::pair< const T &, frequencies > get_smallest_value() const noexcept
Find the largest value.
Definition avl.hpp:167
tree_node * right_right_case(tree_node *const n) const noexcept
Right-right imbalance case.
Definition avl.hpp:630
tree_node * join_shorter(tree_node *T1, tree_node *T2) const noexcept
Join two AVL trees.
Definition avl.hpp:1141
std::size_t total_elements() const noexcept
Total number of elements inserted.
Definition avl.hpp:335
frequencies remove_smallest() noexcept
Remove an element from the tree.
Definition avl.hpp:156
std::pair< const T &, frequencies > get_largest_value() const noexcept
Finds the largest value.
Definition avl.hpp:118
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:825
constexpr int64_t to_int64(const T &t) noexcept
Conversion to int64_t.
Definition basic_convert.hpp:57
constexpr uint64_t to_uint64(const T &t) noexcept
Conversion to uint64_t.
Definition basic_convert.hpp:52
Main namespace of the library.
Definition basic_types.hpp:48
Frequency of a value in the tree v.
Definition avl.hpp:76
bool operator!=(const frequencies &f) const noexcept
Different operator.
Definition avl.hpp:91
std::size_t counter_larger
Number of occurrences of larger elements than v in the tree.
Definition avl.hpp:80
bool operator==(const frequencies &f) const noexcept
Equality comparison.
Definition avl.hpp:84
std::size_t num_nodes_larger
Number of nodes with a key larger than v in the tree.
Definition avl.hpp:82
std::size_t counter_equal
Number of occurrences of v in the tree.
Definition avl.hpp:78
Node of the tree.
Definition avl.hpp:353
void update_height_and_balance_factor() noexcept
Calculate the height and balance factor of this node.
Definition avl.hpp:423
T key
contents of the node
Definition avl.hpp:355
std::size_t left_size() const noexcept
Returns the size of the left subtree.
Definition avl.hpp:406
std::size_t right_size() const noexcept
Returns the size of the right subtree.
Definition avl.hpp:409
tree_node * left
Pointer to the left subtree.
Definition avl.hpp:391
void update_size() noexcept
Computes the size of the subtree rooted at this node.
Definition avl.hpp:434
void update() noexcept
Updates information of this node.
Definition avl.hpp:456
void update_count() noexcept
Computes the size of the subtree rooted at this node.
Definition avl.hpp:442
std::size_t height
Maximum height of the left and right subtrees' height.
Definition avl.hpp:379
std::size_t tree_counter
Total number of occurrences in the nodes in the subtree rooted at this node.
Definition avl.hpp:376
void replace_with(tree_node *const n) noexcept
Replace this node with either its left or right child.
Definition avl.hpp:478
std::size_t node_counter
Amount of occurrences of key.
Definition avl.hpp:357
std::size_t right_counter() const noexcept
Returns the size of the right subtree.
Definition avl.hpp:416
std::size_t left_counter() const noexcept
Returns the total occurrences of the left subtree.
Definition avl.hpp:413
char side
Side of this node with respect to its parent.
Definition avl.hpp:403
int64_t balance_factor
Balance factor of a node:
Definition avl.hpp:386
std::size_t tree_size
Amount of nodes in the subtree rooted at this node.
Definition avl.hpp:364
tree_node * right
Pointer to the right subtree.
Definition avl.hpp:393
tree_node * parent
Pointer to the parent of this node.
Definition avl.hpp:389