From a0ce38e2eed87b53ec8c70674e891211d42f0628 Mon Sep 17 00:00:00 2001 From: Pagwin Date: Fri, 22 Nov 2024 19:24:06 -0500 Subject: [PATCH] bug fixing and realizing that I need to fix my way of determining the next and prior node --- Map.hpp | 58 ++++++++++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/Map.hpp b/Map.hpp index a4e5191..33369f8 100644 --- a/Map.hpp +++ b/Map.hpp @@ -48,6 +48,7 @@ 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) { @@ -61,6 +62,7 @@ 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; @@ -68,7 +70,7 @@ template struct BookKeeping { // reference to a pointer because the alternatives were worse inline Self *child(Direction dir) { auto ret = c_select(dir); - return ret.has_value() ? &container.nodes[left.value()] : nullptr; + return ret.has_value() ? &container.nodes[ret.value()] : nullptr; } inline std::optional c_select(Direction dir) { switch (dir) { @@ -151,8 +153,9 @@ template struct BookKeeping { Self *S = P->child(!dir); Self *C; + // this tidbit is wrong and wikipedia is wrong to have this assert it seems // this method shouldn't be called in cases where this assert will trip - assert(S != nullptr); + // assert(S != nullptr); C = S->child(dir); P->c_trans(!dir, C); @@ -438,31 +441,13 @@ private: void handle_root_rotation(Node *grandparent, Node *parent, Node *inserting, Direction dir) { // making inner grandchild into outer grandchild + if (inserting == parent->child(!dir)) { parent->rotate(dir); inserting = parent; parent = grandparent->child(dir); } - // RotateDirRoot(T,G,1-dir); - Node *gr_grandparent = grandparent->par(); - Node *sibling = grandparent->child(!dir); - assert(sibling != nullptr); - Node *child = sibling->child(dir); - grandparent->c_trans(!dir, child); - sibling->c_trans(dir, grandparent); - grandparent->set_par(sibling); - sibling->set_par(gr_grandparent); - if (gr_grandparent != nullptr) { - Direction grandparent_direction; - if (gr_grandparent->l() == grandparent) { - grandparent_direction = Direction::Left; - } else { - grandparent_direction = Direction::Right; - } - gr_grandparent->c_trans(grandparent_direction, sibling); - } else { - this->root = sibling - &this->nodes[0]; - } + grandparent->rotate(!dir); parent->color = Color::Black; grandparent->color = Color::Red; @@ -488,28 +473,22 @@ 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; } - switch (dir) { - case Direction::Left: - this->nodes[parent.value()].left = to_insert; - break; - case Direction::Right: - this->nodes[parent.value()].right = to_insert; - break; - } - do { // don't need to keep track of these in between loops they get // recalculated @@ -539,7 +518,13 @@ private: if (!uncle.has_value() || this->nodes[uncle.value()].color == Color::Black) { - // case 5 and 6 + if (to_insert == this->nodes[parent.value()].c_select(!dir)) { + // case 5 + this->nodes[parent.value()].rotate(dir); + to_insert = parent; + parent = this->nodes[grandparent.value()].c_select(dir); + } + // case 6 this->handle_root_rotation(grandparent, parent, to_insert, parent_direction); return; @@ -718,15 +703,18 @@ 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(); @@ -735,13 +723,16 @@ public: } // 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 (next.has_value()) { + // TODO: recalc this this->nodes[next.value()].prev = prev; } } @@ -755,8 +746,11 @@ public: 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; }