14#include <unordered_map>
22template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
26 :
base(comparator, allocator) {}
28template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
31 :
base(other.comparator, other.allocator), based_on(other.based_on) {
35template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
43 based_on = other.based_on;
50template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
53 :
base(std::move(other.comparator), std::move(other.allocator)),
54 roots(std::move(other.roots)), node_counts(std::move(other.node_counts)),
55 based_on(std::move(other.based_on)) {}
57template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
61 this->comparator = std::move(other.comparator);
62 this->allocator = std::move(other.allocator);
64 roots = std::move(other.roots);
65 node_counts = std::move(other.node_counts);
66 based_on = std::move(other.based_on);
71template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
73 TAlloc>::~persistent_avl_tree() noexcept {
79template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
83 node_counts = other.node_counts;
85 std::unordered_map<node_ptr, node_ptr> old_to_new;
86 std::vector<std::pair<node_ptr, node_ptr *>> stack;
88 roots.assign(other.roots.size(),
nullptr);
90 for (
int version = 0;
static_cast<size_t>(version) < other.roots.size();
92 node_ptr root = other.roots[version];
94 if (root ==
nullptr) {
98 if (root->version != version) {
99 roots[version] = old_to_new.at(root);
104 stack.push_back(std::make_pair(root, &roots[version]));
106 while (!stack.empty()) {
107 auto [node, location] = stack.back();
110 node_ptr new_node = copy_node(node, version);
111 old_to_new[node] = new_node;
112 *location = new_node;
114 if (node->left !=
nullptr) {
115 if (node->left->version == version) {
117 std::make_pair(node->left, &new_node->left));
121 new_node->left = old_to_new.at(node->left);
124 if (node->right !=
nullptr) {
125 if (node->right->version == version) {
127 std::make_pair(node->right, &new_node->right));
131 new_node->right = old_to_new.at(node->right);
138template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
140persistent_avl_tree<TKey, TItem, TKeyComp, TAlloc>::copy_node(
141 node_ptr node, version_type version) {
143 typename base::item_type new_item = node->item;
144 node_ptr new_node = this->create_node(new_item);
145 new_node->sign = node->sign;
146 new_node->left = node->left;
147 new_node->right = node->right;
148 new_node->version = version;
152template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
153template <std::invocable TCallback>
155persistent_avl_tree<TKey, TItem, TKeyComp, TAlloc>::copy_node(
156 node_ptr node, TCallback &&callback, version_type version) {
157 node_ptr new_node = this->create_node(std::forward<TCallback>(callback));
158 new_node->sign = node->sign;
159 new_node->left = node->left;
160 new_node->right = node->right;
161 new_node->version = version;
165template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
166typename persistent_avl_tree<TKey, TItem, TKeyComp, TAlloc>::path_type
167persistent_avl_tree<TKey, TItem, TKeyComp, TAlloc>::copy_path(
168 const path_type &path, node_ptr new_child, version_type version) {
172 new_path.resize(path.size(), std::make_pair(
nullptr,
false));
174 for (
int i = path.size() - 1; i >= 0; --i) {
175 auto [parent, child_is_right] = path[i];
177 node_ptr new_parent = copy_node(parent, version);
179 new_path[i] = std::make_pair(new_parent, child_is_right);
181 if (child_is_right) {
182 new_parent->right = new_child;
185 new_parent->left = new_child;
188 new_child = new_parent;
194template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
197 const path_type &parents) {
199 if (child_is_right) {
200 parent->right = child->left;
201 child->left = parent;
204 parent->left = child->right;
205 child->right = parent;
208 if (parent_index == 0) {
210 roots.back() = child;
213 auto [grandpa, parent_is_right] = parents[parent_index - 1];
215 if (parent_is_right) {
216 grandpa->right = child;
219 grandpa->left = child;
224template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
225void persistent_avl_tree<TKey, TItem, TKeyComp, TAlloc>::double_rotate(
226 node_ptr parent, node_ptr child, node_ptr grand_child,
bool child_is_right,
227 int parent_index,
const path_type &parents) {
229 if (child_is_right) {
230 parent->right = grand_child->left;
231 child->left = grand_child->right;
232 grand_child->left = parent;
233 grand_child->right = child;
236 parent->left = grand_child->right;
237 child->right = grand_child->left;
238 grand_child->left = child;
239 grand_child->right = parent;
242 if (parent_index == 0) {
243 roots.back() = grand_child;
246 auto [grandpa, parent_is_right] = parents[parent_index - 1];
248 if (parent_is_right) {
249 grandpa->right = grand_child;
252 grandpa->left = grand_child;
259template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
264 if (!is_valid_version(version)) {
265 return std::vector<node_ptr>{};
268 std::vector<node_ptr> result;
269 std::stack<node_ptr> stack;
270 node_ptr current = roots[version];
272 while (current !=
nullptr || !stack.empty()) {
273 while (current !=
nullptr) {
275 current = current->left;
278 current = stack.top();
281 result.push_back(current);
283 current = current->right;
289template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
294 if (!is_valid_version(version)) {
301 if (node ==
nullptr) {
304 if (this->comparator(key, node->item)) {
307 else if (this->comparator(node->item, key)) {
318template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
321 for (
version_type version = roots.size() - 1; version >= 0; --version) {
324 while (node !=
nullptr && node->version == version) {
325 if (node->left !=
nullptr && node->left->version == version) {
327 node->left = tmp->right;
333 this->destroy_node(node);
344template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
345template <std::invocable TCallback>
346std::pair<typename persistent_avl_tree<TKey, TItem, TKeyComp, TAlloc>::node_ptr,
349 TCallback &&callback,
353 if (!is_valid_version(version)) {
359 if (version == -1 || roots[version] ==
nullptr) {
361 this->create_node(std::forward<TCallback>(callback));
362 new_root->version = new_version;
364 roots.push_back(new_root);
365 node_counts.push_back(1);
366 based_on.push_back(version);
368 return std::make_pair(new_root,
true);
376 if (this->comparator(key, node->item)) {
377 parents.push_back(std::make_pair(node,
false));
379 if (node->left ==
nullptr) {
380 new_node = this->create_node(std::forward<TCallback>(callback));
381 new_node->version = new_version;
387 else if (this->comparator(node->item, key)) {
388 parents.push_back(std::make_pair(node,
true));
390 if (node->right ==
nullptr) {
391 new_node = this->create_node(std::forward<TCallback>(callback));
392 new_node->version = new_version;
400 return std::make_pair(node,
false);
406 copy_node(node, std::forward<TCallback>(callback), new_version);
407 new_node->version = new_version;
409 path_type new_parents = copy_path(parents, new_node, new_version);
411 if (new_parents.empty()) {
412 roots.push_back(new_node);
415 auto [last_parent, attach_right] = new_parents.back();
417 last_parent->right = new_node;
420 last_parent->left = new_node;
422 roots.push_back(new_parents[0].first);
426 node_counts.push_back(node_counts[version]);
427 based_on.push_back(version);
429 return std::make_pair(new_node,
false);
433 path_type new_parents = copy_path(parents, new_node, new_version);
435 auto [last_parent, attach_right] = new_parents.back();
437 last_parent->right = new_node;
440 last_parent->left = new_node;
443 roots.push_back(new_parents[0].first);
444 node_counts.push_back(node_counts[version] + 1);
445 based_on.push_back(version);
450 int parent_index =
static_cast<int>(new_parents.size()) - 1;
452 while (parent_index >= 0) {
453 auto [parent, node_is_right] = new_parents[parent_index];
457 if (parent->sign == -positive) {
462 if (parent->sign == positive) {
465 if (node->sign == positive) {
466 rotate(parent, node, node_is_right, parent_index, new_parents);
473 node_ptr child = (positive == 1) ? node->left : node->right;
475 double_rotate(parent, node, child, node_is_right, parent_index,
479 if (child->sign == positive) {
481 parent->sign = -positive;
483 else if (child->sign == -positive) {
484 node->sign = +positive;
499 parent->sign = positive;
504 return std::make_pair(new_node,
true);
507template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
509 TAlloc>::version_type>
513 if (!is_valid_version(version)) {
514 return std::make_pair(
false, version);
517 if (roots[version] ==
nullptr) {
518 return std::make_pair(
false, version);
528 if (node ==
nullptr) {
529 return std::make_pair(
false, version);
532 if (this->comparator(key, node->item)) {
533 parents.push_back(std::make_pair(node,
false));
536 else if (this->comparator(node->item, key)) {
537 parents.push_back(std::make_pair(node,
true));
549 node_counts.push_back(node_counts[version] - 1);
550 based_on.push_back(version);
554 path_type new_parents = copy_path(parents,
nullptr, new_version);
558 if (new_parents.empty()) {
559 roots.push_back(
nullptr);
560 path_end_location = &roots.back();
563 roots.push_back(new_parents[0].first);
565 auto [end, place_right] = new_parents.back();
568 path_end_location = &end->right;
571 path_end_location = &end->left;
580 if (left_child !=
nullptr && right_child !=
nullptr) {
583 if (candidate->left ==
nullptr) {
586 node_ptr replacement = copy_node(candidate, new_version);
588 replacement->left = left_child;
589 replacement->sign = node->sign;
591 *path_end_location = replacement;
593 new_parents.push_back(std::make_pair(replacement,
true));
596 path_type min_search_path;
599 while ((min_candidate = candidate->left) !=
nullptr) {
600 min_search_path.push_back(std::make_pair(candidate,
false));
601 candidate = min_candidate;
604 path_type new_min_path =
605 copy_path(min_search_path, candidate->right, new_version);
607 node_ptr replacement = copy_node(candidate, new_version);
609 replacement->left = left_child;
610 replacement->right = new_min_path[0].first;
611 replacement->sign = node->sign;
613 *path_end_location = replacement;
615 new_parents.push_back(std::make_pair(replacement,
true));
617 for (
size_t i = 0; i < new_min_path.size(); ++i) {
618 new_parents.push_back(new_min_path[i]);
622 else if (left_child !=
nullptr || right_child !=
nullptr) {
625 if (left_child !=
nullptr) {
626 replacement = copy_node(left_child, new_version);
629 replacement = copy_node(right_child, new_version);
632 *path_end_location = replacement;
635 int parent_index =
static_cast<int>(new_parents.size()) - 1;
637 while (parent_index >= 0) {
638 auto [parent, remove_was_right] = new_parents[parent_index];
642 if (parent->sign == 0) {
643 parent->sign = -positive;
644 return std::make_pair(
true, new_version);
646 else if (parent->sign == positive) {
653 const bool child_is_right = !remove_was_right;
655 child_is_right ? parent->right : parent->left;
656 node_ptr child = copy_node(child_original, new_version);
660 if (child->sign == -positive) {
661 rotate(parent, child, child_is_right, parent_index,
667 else if (child->sign == 0) {
668 rotate(parent, child, child_is_right, parent_index,
670 child->sign = positive;
671 parent->sign = -positive;
672 return std::make_pair(
true, new_version);
676 child_is_right ? child->left : child->right;
678 copy_node(grand_child_original, new_version);
680 double_rotate(parent, child, grand_child, child_is_right,
681 parent_index, new_parents);
683 if (grand_child->sign == positive) {
685 child->sign = -positive;
687 else if (grand_child->sign == -positive) {
688 parent->sign = positive;
696 grand_child->sign = 0;
705 return std::make_pair(
true, new_version);
708template <
class TKey,
class TItem,
class TKeyComp,
class TAlloc>
712 if (!is_valid_version(version)) {
718 if (root ==
nullptr) {
723 std::stack<std::pair<node_ptr, int>> stack;
724 stack.emplace(root, 0);
726 while (!stack.empty()) {
727 auto [node, level] = stack.top();
730 height = std::max(level, height);
732 if (node->left !=
nullptr) {
733 stack.emplace(node->left, level + 1);
736 if (node->right !=
nullptr) {
737 stack.emplace(node->right, level + 1);
Declarations of the persistent AVL tree.
Base class for avl trees.
Definition _avl_common.hpp:76
avl_sign_type sign_type
Definition _avl_common.hpp:103
TKeyComp comparator_type
Definition _avl_common.hpp:80
TAlloc allocator_type
Definition _avl_common.hpp:81
comparator_type comparator
Definition _avl_common.hpp:105
node_alloc_type allocator
Definition _avl_common.hpp:106
Persitent AVL tree implementation.
Definition _persistent_avl.hpp:97
persistent_avl_tree & operator=(const persistent_avl_tree &other)
Copies another tree.
Definition _persistent_avl.ipp:37
persistent_avl_tree(const typename base::comparator_type &comparator, const typename base::allocator_type &allocator)
Constructs new persistent AVL tree.
Definition _persistent_avl.ipp:23
std::pair< node_ptr, bool > insert(const key_type &key, TCallback &&callback, version_type version, bool do_assign)
Inserts an item to the tree.
node_ptr find(const key_type &key, version_type version) const noexcept
Finds a node with the given key in the given version, if there isn't any returns a nullptr.
Definition _persistent_avl.ipp:291
persistent_avl_version_type version_type
Definition _persistent_avl.hpp:99
std::pair< bool, version_type > erase(const key_type &key, version_type version) noexcept
Erases the node with the given key or does nothing if the key does not exist.
Definition _persistent_avl.ipp:510
void clear_all() noexcept
Erases the whole tree across versions.
Definition _persistent_avl.ipp:319
int get_height(version_type version) const
Returns the height of the tree in the given version.
Definition _persistent_avl.ipp:709
typename base::node_ptr node_ptr
Definition _persistent_avl.hpp:107
typename base::key_type key_type
Definition _persistent_avl.hpp:108
std::vector< node_ptr > list_in_order(version_type version) const noexcept
Returns a vector of nodes sorted by keys.
Definition _persistent_avl.ipp:262
Declarations of the persistent map.
Definition _avl.hpp:14