23template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
25 const typename base::comparator_type &comparator,
26 const typename base::allocator_type &allocator)
27 :
base(comparator, allocator) {}
29template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
31 :
base(other.comparator, other.allocator) {
35template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
46template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
48 :
base(std::move(other.comparator), std::move(other.allocator)) {
50 this->node_count = other.node_count;
56template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
59 this->comparator = std::move(other.comparator);
60 this->allocator = std::move(other.allocator);
63 this->node_count = other.node_count;
71template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
78template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
81 this->node_count = other.node_count;
83 root = this->create_node(other.root->item);
84 root->sign = other.root->sign;
86 std::stack<std::pair<node_ptr, node_ptr>> stack;
88 stack.push(std::make_pair(root, other.root));
90 while (!stack.empty()) {
91 auto [node, other_node] = stack.top();
94 if (other_node->left !=
nullptr) {
95 node->left = this->create_node(other_node->left->item);
96 node->left->parent = node;
97 node->left->sign = other_node->left->sign;
99 stack.push(std::make_pair(node->left, other_node->left));
102 if (other_node->right !=
nullptr) {
103 node->right = this->create_node(other_node->right->item);
104 node->right->parent = node;
105 node->right->sign = other_node->right->sign;
107 stack.push(std::make_pair(node->right, other_node->right));
112template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
113void avl_tree<TKey, TItem, TKeyComp, TAlloc>::rotate(node_ptr x)
noexcept {
114 node_ptr y = x->parent;
115 node_ptr p = y->parent;
156template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
159 const key_type &key)
const noexcept {
163 if (node ==
nullptr) {
166 if (this->comparator(key, node->item)) {
169 else if (this->comparator(node->item, key)) {
178template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
182 if (node ==
nullptr) {
186 if (node->right ==
nullptr) {
187 while (node->parent !=
nullptr) {
188 if (!is_right_child(node)) {
196 return this->min_from(node->right);
199template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
203 if (node ==
nullptr) {
207 if (node->left ==
nullptr) {
208 while (node->parent !=
nullptr) {
209 if (is_right_child(node)) {
217 return this->max_from(node->left);
220template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
224 const key_type &key)
const noexcept {
225 if (root ==
nullptr) {
232 if (this->comparator(key, node->item)) {
233 if (node->left ==
nullptr) {
238 else if (this->comparator(node->item, key)) {
239 if (node->right ==
nullptr) {
240 return successor(node);
245 if constexpr (lower) {
249 return successor(node);
257template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
261 while (node !=
nullptr) {
262 if (node->left !=
nullptr) {
264 node->left = tmp->right;
270 this->destroy_node(node);
276 this->node_count = 0;
279template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
280template <
class TInsertCallback,
class TAssignCallback>
281std::pair<typename avl_tree<TKey, TItem, TKeyComp, TAlloc>::node_ptr,
bool>
283 const key_type &key, TInsertCallback &&insert_callback,
284 TAssignCallback &&assign_callback) {
285 if (root ==
nullptr) {
287 this->create_node(std::forward<TInsertCallback>(insert_callback));
289 return std::make_pair(root,
true);
297 if (this->comparator(key, node->item)) {
298 if (node->left ==
nullptr) {
299 new_node = this->create_node(
300 std::forward<TInsertCallback>(insert_callback));
302 node->left = new_node;
303 node->left->parent = node;
311 else if (this->comparator(node->item, key)) {
312 if (node->right ==
nullptr) {
313 new_node = this->create_node(
314 std::forward<TInsertCallback>(insert_callback));
316 node->right = new_node;
317 node->right->parent = node;
326 assign_callback(node->item);
327 return std::make_pair(node,
false);
333 while (node->parent !=
nullptr) {
334 node_ptr parent = node->parent;
336 const typename base::sign_type positive =
337 (is_right_child(node)) ? +1 : -1;
339 if (parent->sign == -positive) {
344 if (parent->sign == positive) {
347 if (node->sign == positive) {
354 node_ptr child = (positive == 1) ? node->left : node->right;
359 if (child->sign == positive) {
361 parent->sign = -positive;
363 else if (child->sign == -positive) {
364 node->sign = +positive;
379 parent->sign = positive;
383 return std::make_pair(new_node,
true);
386template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
391 bool from_right =
false;
393 if (parent !=
nullptr) {
394 from_right = is_right_child(node);
401 node_ptr balance_from_node = parent;
402 bool balance_from_right = from_right;
405 replacement =
nullptr;
407 else if (node->left ==
nullptr) {
408 replacement = node->right;
414 else if (node->right ==
nullptr) {
415 replacement = node->left;
419 replacement = this->min_from(node->right);
421 if (replacement->parent != node) {
425 balance_from_node = replacement->parent;
426 balance_from_right =
false;
428 par->left = replacement->right;
431 if (par->left !=
nullptr) {
432 par->left->parent = par;
435 replacement->right = node->right;
436 replacement->right->parent = replacement;
441 balance_from_node = replacement;
442 balance_from_right =
true;
446 replacement->sign = node->sign;
448 replacement->left = node->left;
449 if (replacement->left !=
nullptr) {
450 replacement->left->parent = replacement;
456 this->destroy_node(node);
461 if (parent ==
nullptr) {
465 else if (from_right) {
466 parent->right = replacement;
469 parent->left = replacement;
472 if (replacement !=
nullptr) {
473 replacement->parent = parent;
478 if (balance_from_node ==
nullptr) {
483 node_ptr next_node = balance_from_node->parent;
484 bool next_from_right =
false;
485 if (next_node !=
nullptr) {
486 next_from_right = is_right_child(balance_from_node);
489 const typename base::sign_type positive = balance_from_right ? +1 : -1;
491 if (balance_from_node->sign == 0) {
492 balance_from_node->sign = -positive;
496 else if (balance_from_node->sign == -positive) {
499 node_ptr child = balance_from_right ? balance_from_node->left
500 : balance_from_node->right;
504 if (child->sign == -positive) {
507 balance_from_node->sign = 0;
510 else if (child->sign == 0) {
512 child->sign = positive;
513 balance_from_node->sign = -positive;
518 balance_from_right ? child->right : child->left;
523 if (grand_child->sign == positive) {
524 balance_from_node->sign = 0;
525 child->sign = -positive;
527 else if (grand_child->sign == -positive) {
528 balance_from_node->sign = positive;
532 balance_from_node->sign = 0;
536 grand_child->sign = 0;
542 balance_from_node->sign = 0;
546 if (next_node ==
nullptr) {
550 balance_from_node = next_node;
551 balance_from_right = next_from_right;
557template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
559 if (root ==
nullptr) {
564 std::stack<std::pair<node_ptr, int>> stack;
565 stack.emplace(root, 0);
567 while (!stack.empty()) {
568 auto [node, level] = stack.top();
571 height = std::max(level, height);
573 if (node->left !=
nullptr) {
574 stack.emplace(node->left, level + 1);
577 if (node->right !=
nullptr) {
578 stack.emplace(node->right, level + 1);
587template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
590 auto get_repr = [](
node_ptr node) -> std::string {
591 if (node ==
nullptr) {
595 if constexpr (std::is_convertible_v<
decltype(node->item),
597 return std::string(node->item);
599 else if constexpr (
requires { std::to_string(node->item); }) {
600 return std::to_string(node->item);
602 else if constexpr (
requires { std::format(
"{}", node->item); }) {
603 return std::format(
"{}", node->item);
606 return std::format(
"{}",
static_cast<const void *
>(node));
610 auto get_id = [](
node_ptr node) -> std::string {
611 return std::format(
"{}",
static_cast<const void *
>(node));
614 std::stringstream ss;
618 std::stack<node_ptr> s;
619 if (root !=
nullptr) {
627 std::string sign =
"0";
629 if (node->sign == +1) {
632 else if (node->sign == -1) {
636 ss <<
" " << get_id(node) <<
" [label=\"" << get_repr(node) <<
"\\n"
640 ss <<
", style=filled, fillcolor=lightblue";
645 if (node->left !=
nullptr) {
646 ss <<
" " << get_id(node) <<
" -> " << get_id(node->left)
650 else if (print_invis) {
651 ss <<
" inv" << get_id(node) <<
"L [style=invis];\n";
652 ss <<
" " << get_id(node) <<
" -> inv" << get_id(node)
653 <<
"L [style=invis];\n";
655 if (node->right !=
nullptr) {
656 ss <<
" " << get_id(node) <<
" -> " << get_id(node->right)
660 else if (print_invis) {
661 ss <<
" inv" << get_id(node) <<
"R [style=invis];\n";
662 ss <<
" " << get_id(node) <<
" -> inv" << get_id(node)
663 <<
"R [style=invis];\n";
Declarations of the ethereal AVL tree.
avl_sign_type sign_type
Definition _avl_common.hpp:103
comparator_type comparator
Definition _avl_common.hpp:105
node_alloc_type allocator
Definition _avl_common.hpp:106
AVL tree implementation.
Definition _avl.hpp:77
typename base::node_ptr node_ptr
Definition _avl.hpp:83
~avl_tree() noexcept
Destroys the tree.
Definition _avl.ipp:72
void clear() noexcept
Erases the whole tree.
Definition _avl.ipp:258
avl_tree(const typename base::comparator_type &comparator, const typename base::allocator_type &allocator)
Constructs new AVL tree.
Definition _avl.ipp:24
node_ptr successor(node_ptr node) const noexcept
Returns the successor to the node.
Definition _avl.ipp:180
std::pair< node_ptr, bool > insert(const key_type &key, TInsertCallback &&insert_callback, TAssignCallback &&assign_callback)
Inserts an item to the tree.
int get_height() const
Returns the current height of the tree.
Definition _avl.ipp:558
std::string to_dot(bool print_invis) const
Returns the dot representation of the tree.
Definition _avl.ipp:589
node_ptr find(const key_type &key) const noexcept
Finds a node with the given key, if there isn't any returns a nullptr.
Definition _avl.ipp:158
void erase(node_ptr node) noexcept
Erases the node.
Definition _avl.ipp:387
node_ptr predecessor(node_ptr node) const noexcept
Returns the predecessor to the node.
Definition _avl.ipp:201
avl_tree & operator=(const avl_tree &other)
Copies another tree.
Definition _avl.ipp:37
node_ptr bound(const key_type &key) const noexcept
A 2-in-1 function for both lower and upper bounds accessing.
Definition _avl.ipp:223
typename base::key_type key_type
Definition _avl.hpp:84
Declarations of the persistent map.
Definition _avl.hpp:14