diff --git a/Map.hpp b/Map.hpp index 33369f8..052da40 100644 --- a/Map.hpp +++ b/Map.hpp @@ -48,7 +48,6 @@ template struct BookKeeping { BookKeeping(BookKeeping const &rhs) : container{rhs.container}, value{rhs.value}, // self{rhs.self}, color{rhs.color}, parent{rhs.parent}, left{rhs.left}, right{rhs.right}, - // TODO: recalc this prev{rhs.prev}, next{rhs.next} {} // if pointing to different containers throws BookKeeping &operator=(BookKeeping const &rhs) { @@ -62,7 +61,6 @@ template struct BookKeeping { this->parent = rhs.parent; this->left = rhs.left; this->right = rhs.right; - // TODO: recalc this this->prev = rhs.prev; this->next = rhs.next; return *this; @@ -353,6 +351,55 @@ private: std::vector nodes; std::size_t size_diff; + std::optional pred(std::size_t node) { + if (this->nodes[node].left.has_value()) { + std::size_t store = this->nodes[node].left.value(); + while (this->nodes[store].right.has_value()) { + store = this->nodes[node].right.value(); + } + return store; + } else { + if (!this->nodes[node].parent.has_value()) { + return std::nullopt; + } + + std::size_t prev_store = node; + std::size_t store = this->nodes[node].parent.value(); + while (this->nodes[store].parent.has_value()) { + if (this->nodes[store].right == prev_store) { + return store; + } + prev_store = store; + store = this->nodes[store].parent.value(); + } + return std::nullopt; + } + } + std::optional succ(std::size_t node) { + if (this->nodes[node].right.has_value()) { + std::size_t store = this->nodes[node].right.value(); + while (this->nodes[store].left.has_value()) { + store = this->nodes[node].left.value(); + } + return store; + } else { + if (!this->nodes[node].parent.has_value()) { + return std::nullopt; + } + + std::size_t prev_store = node; + std::size_t store = this->nodes[prev_store].parent.value(); + while (this->nodes[store].parent.has_value()) { + if (this->nodes[store].left == prev_store) { + return store; + } + prev_store = store; + store = this->nodes[store].parent.value(); + } + return std::nullopt; + } + } + public: Map() : root{std::nullopt}, min{std::nullopt}, max{std::nullopt}, nodes{}, @@ -473,18 +520,9 @@ private: switch (dir) { case Direction::Left: - // TODO: recalc this - this->nodes[to_insert.value()].next = parent; - this->nodes[to_insert.value()].prev = this->nodes[parent.value()].prev; - this->nodes[parent.value()].prev = to_insert; this->nodes[parent.value()].left = to_insert; break; case Direction::Right: - // TODO: recalc this - this->nodes[to_insert.value()].prev = parent; - this->nodes[to_insert.value()].next = this->nodes[parent.value()].next; - // TODO: recalc this - this->nodes[parent.value()].next = to_insert; this->nodes[parent.value()].right = to_insert; break; } @@ -585,14 +623,21 @@ public: if (min == std::nullopt || val.first < this->nodes[min.value()].value.first) { min = nodes.size() - 1; - nodes.back().prev = std::nullopt; } if (max == std::nullopt || val.first > this->nodes[max.value()].value.first) { max = nodes.size() - 1; - nodes.back().next = std::nullopt; } - + Ref_T successor = this->succ(this->nodes.size() - 1); + Ref_T predessor = this->pred(this->nodes.size() - 1); + if (successor.has_value()) { + this->nodes[successor.value()].prev = this->nodes.size() - 1; + } + this->nodes[this->nodes.size() - 1].next = successor; + if (predessor.has_value()) { + this->nodes[predessor.value()].next = this->nodes.size() - 1; + } + this->nodes[this->nodes.size() - 1].prev = successor; return std::make_pair(Iterator(*this, nodes.size() - 1), ret); } template void insert(IT_T range_beg, IT_T range_end) { @@ -688,7 +733,6 @@ private: } public: - // TODO: check that the way of reconnecting next and prev works void erase(Iterator pos) { this->size_diff++; // simple cases @@ -703,61 +747,58 @@ public: } // 2 children if (ref->l() != nullptr && ref->r() != nullptr) { - // TODO: recalc this Ref_T next = ref->next; - Ref_T prev = ref->prev; *ref = this->nodes[next.value()]; - // TODO: recalc this - this->nodes[prev.value()].next = next; - this->nodes[next.value()].prev = prev; this->erase(Iterator{*this, next}); } // single child which is left else if (ref->l() != nullptr && ref->r() == nullptr) { - // TODO: recalc this - Ref_T next = ref->next; - Ref_T prev = ref->prev; - *ref = *ref->l(); - this->nodes[prev.value()].next = next; - this->nodes[next.value()].prev = prev; + if (ref->par()->l() == ref) { + ref->par()->set_l(ref->l()); + } else { + ref->par()->set_r(ref->l()); + } + if (ref->color == Color::Black) { + ref->l()->color = Color::Black; + } } // single child which is right else if (ref->l() == nullptr && ref->r() != nullptr) { - // TODO: recalc this - Ref_T next = ref->next; - Ref_T prev = ref->prev; - *ref = *ref->r(); - if (prev.has_value()) { - // TODO: recalc this - this->nodes[prev.value()].next = next; + if (ref->par()->l() == ref) { + ref->par()->set_l(ref->r()); + } else { + ref->par()->set_r(ref->r()); } - if (next.has_value()) { - // TODO: recalc this - this->nodes[next.value()].prev = prev; + if (ref->color == Color::Black) { + ref->r()->color = Color::Black; } } // no children and root - else if (ref->l() == nullptr && ref->r() == nullptr) { + else if (this->root == pos.ref && ref->l() == nullptr && + ref->r() == nullptr) { this->root = std::nullopt; } // no children and red - else if (ref->l() == nullptr && ref->r() == nullptr) { - Node *next = - ref->next.has_value() ? &this->nodes[ref->next.value()] : nullptr; - Node *prev = - ref->prev.has_value() ? &this->nodes[ref->prev.value()] : nullptr; - - // TODO: recalc this - prev->next = next != nullptr ? std::optional{next - &this->nodes[0]} - : std::nullopt; - // TODO: recalc this - next->prev = prev != nullptr ? std::optional{prev - &this->nodes[0]} - : std::nullopt; + else if (ref->color == Color::Red && ref->l() == nullptr && + ref->r() == nullptr) { + if (ref->parent.has_value()) { + if (this->nodes[ref->parent.value()].right == pos.ref.value()) { + this->nodes[ref->parent.value()].right = std::nullopt; + } else { + this->nodes[ref->parent.value()].left = std::nullopt; + } + } } // complicated case of black node with no kids else { this->complex_erase(pos); } + if (ref->next.has_value()) { + this->nodes[ref->next.value()].prev = this->pred(ref->next.value()); + } + if (ref->prev.has_value()) { + this->nodes[ref->next.value()].next = this->succ(ref->next.value()); + } } void erase(const Key_T &key) { this->erase(this->find(key)); } void clear() {