bug fixing and realizing that I need to fix my way of determining the next and prior node

This commit is contained in:
Pagwin 2024-11-22 19:24:06 -05:00
parent 88194b9a5b
commit a0ce38e2ee
No known key found for this signature in database
GPG key ID: 81137023740CA260

58
Map.hpp
View file

@ -48,6 +48,7 @@ template <typename Key_T, typename Mapped_T> 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 <typename Key_T, typename Mapped_T> 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 <typename Key_T, typename Mapped_T> 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<std::size_t> c_select(Direction dir) {
switch (dir) {
@ -151,8 +153,9 @@ template <typename Key_T, typename Mapped_T> 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;
}