bug fixing and realizing that I need to fix my way of determining the next and prior node
This commit is contained in:
parent
88194b9a5b
commit
a0ce38e2ee
1 changed files with 26 additions and 32 deletions
58
Map.hpp
58
Map.hpp
|
@ -48,6 +48,7 @@ template <typename Key_T, typename Mapped_T> struct BookKeeping {
|
||||||
BookKeeping(BookKeeping const &rhs)
|
BookKeeping(BookKeeping const &rhs)
|
||||||
: container{rhs.container}, value{rhs.value}, // self{rhs.self},
|
: container{rhs.container}, value{rhs.value}, // self{rhs.self},
|
||||||
color{rhs.color}, parent{rhs.parent}, left{rhs.left}, right{rhs.right},
|
color{rhs.color}, parent{rhs.parent}, left{rhs.left}, right{rhs.right},
|
||||||
|
// TODO: recalc this
|
||||||
prev{rhs.prev}, next{rhs.next} {}
|
prev{rhs.prev}, next{rhs.next} {}
|
||||||
// if pointing to different containers throws
|
// if pointing to different containers throws
|
||||||
BookKeeping &operator=(BookKeeping const &rhs) {
|
BookKeeping &operator=(BookKeeping const &rhs) {
|
||||||
|
@ -61,6 +62,7 @@ template <typename Key_T, typename Mapped_T> struct BookKeeping {
|
||||||
this->parent = rhs.parent;
|
this->parent = rhs.parent;
|
||||||
this->left = rhs.left;
|
this->left = rhs.left;
|
||||||
this->right = rhs.right;
|
this->right = rhs.right;
|
||||||
|
// TODO: recalc this
|
||||||
this->prev = rhs.prev;
|
this->prev = rhs.prev;
|
||||||
this->next = rhs.next;
|
this->next = rhs.next;
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -68,7 +70,7 @@ template <typename Key_T, typename Mapped_T> struct BookKeeping {
|
||||||
// reference to a pointer because the alternatives were worse
|
// reference to a pointer because the alternatives were worse
|
||||||
inline Self *child(Direction dir) {
|
inline Self *child(Direction dir) {
|
||||||
auto ret = c_select(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) {
|
inline std::optional<std::size_t> c_select(Direction dir) {
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
|
@ -151,8 +153,9 @@ template <typename Key_T, typename Mapped_T> struct BookKeeping {
|
||||||
Self *S = P->child(!dir);
|
Self *S = P->child(!dir);
|
||||||
Self *C;
|
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
|
// this method shouldn't be called in cases where this assert will trip
|
||||||
assert(S != nullptr);
|
// assert(S != nullptr);
|
||||||
|
|
||||||
C = S->child(dir);
|
C = S->child(dir);
|
||||||
P->c_trans(!dir, C);
|
P->c_trans(!dir, C);
|
||||||
|
@ -438,31 +441,13 @@ private:
|
||||||
void handle_root_rotation(Node *grandparent, Node *parent, Node *inserting,
|
void handle_root_rotation(Node *grandparent, Node *parent, Node *inserting,
|
||||||
Direction dir) {
|
Direction dir) {
|
||||||
// making inner grandchild into outer grandchild
|
// making inner grandchild into outer grandchild
|
||||||
|
|
||||||
if (inserting == parent->child(!dir)) {
|
if (inserting == parent->child(!dir)) {
|
||||||
parent->rotate(dir);
|
parent->rotate(dir);
|
||||||
inserting = parent;
|
inserting = parent;
|
||||||
parent = grandparent->child(dir);
|
parent = grandparent->child(dir);
|
||||||
}
|
}
|
||||||
// RotateDirRoot(T,G,1-dir);
|
grandparent->rotate(!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];
|
|
||||||
}
|
|
||||||
|
|
||||||
parent->color = Color::Black;
|
parent->color = Color::Black;
|
||||||
grandparent->color = Color::Red;
|
grandparent->color = Color::Red;
|
||||||
|
@ -488,28 +473,22 @@ private:
|
||||||
|
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case Direction::Left:
|
case Direction::Left:
|
||||||
|
// TODO: recalc this
|
||||||
this->nodes[to_insert.value()].next = parent;
|
this->nodes[to_insert.value()].next = parent;
|
||||||
this->nodes[to_insert.value()].prev = this->nodes[parent.value()].prev;
|
this->nodes[to_insert.value()].prev = this->nodes[parent.value()].prev;
|
||||||
this->nodes[parent.value()].prev = to_insert;
|
this->nodes[parent.value()].prev = to_insert;
|
||||||
this->nodes[parent.value()].left = to_insert;
|
this->nodes[parent.value()].left = to_insert;
|
||||||
break;
|
break;
|
||||||
case Direction::Right:
|
case Direction::Right:
|
||||||
|
// TODO: recalc this
|
||||||
this->nodes[to_insert.value()].prev = parent;
|
this->nodes[to_insert.value()].prev = parent;
|
||||||
this->nodes[to_insert.value()].next = this->nodes[parent.value()].next;
|
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()].next = to_insert;
|
||||||
this->nodes[parent.value()].right = to_insert;
|
this->nodes[parent.value()].right = to_insert;
|
||||||
break;
|
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 {
|
do {
|
||||||
// don't need to keep track of these in between loops they get
|
// don't need to keep track of these in between loops they get
|
||||||
// recalculated
|
// recalculated
|
||||||
|
@ -539,7 +518,13 @@ private:
|
||||||
|
|
||||||
if (!uncle.has_value() ||
|
if (!uncle.has_value() ||
|
||||||
this->nodes[uncle.value()].color == Color::Black) {
|
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,
|
this->handle_root_rotation(grandparent, parent, to_insert,
|
||||||
parent_direction);
|
parent_direction);
|
||||||
return;
|
return;
|
||||||
|
@ -718,15 +703,18 @@ public:
|
||||||
}
|
}
|
||||||
// 2 children
|
// 2 children
|
||||||
if (ref->l() != nullptr && ref->r() != nullptr) {
|
if (ref->l() != nullptr && ref->r() != nullptr) {
|
||||||
|
// TODO: recalc this
|
||||||
Ref_T next = ref->next;
|
Ref_T next = ref->next;
|
||||||
Ref_T prev = ref->prev;
|
Ref_T prev = ref->prev;
|
||||||
*ref = this->nodes[next.value()];
|
*ref = this->nodes[next.value()];
|
||||||
|
// TODO: recalc this
|
||||||
this->nodes[prev.value()].next = next;
|
this->nodes[prev.value()].next = next;
|
||||||
this->nodes[next.value()].prev = prev;
|
this->nodes[next.value()].prev = prev;
|
||||||
this->erase(Iterator{*this, next});
|
this->erase(Iterator{*this, next});
|
||||||
}
|
}
|
||||||
// single child which is left
|
// single child which is left
|
||||||
else if (ref->l() != nullptr && ref->r() == nullptr) {
|
else if (ref->l() != nullptr && ref->r() == nullptr) {
|
||||||
|
// TODO: recalc this
|
||||||
Ref_T next = ref->next;
|
Ref_T next = ref->next;
|
||||||
Ref_T prev = ref->prev;
|
Ref_T prev = ref->prev;
|
||||||
*ref = *ref->l();
|
*ref = *ref->l();
|
||||||
|
@ -735,13 +723,16 @@ public:
|
||||||
}
|
}
|
||||||
// single child which is right
|
// single child which is right
|
||||||
else if (ref->l() == nullptr && ref->r() != nullptr) {
|
else if (ref->l() == nullptr && ref->r() != nullptr) {
|
||||||
|
// TODO: recalc this
|
||||||
Ref_T next = ref->next;
|
Ref_T next = ref->next;
|
||||||
Ref_T prev = ref->prev;
|
Ref_T prev = ref->prev;
|
||||||
*ref = *ref->r();
|
*ref = *ref->r();
|
||||||
if (prev.has_value()) {
|
if (prev.has_value()) {
|
||||||
|
// TODO: recalc this
|
||||||
this->nodes[prev.value()].next = next;
|
this->nodes[prev.value()].next = next;
|
||||||
}
|
}
|
||||||
if (next.has_value()) {
|
if (next.has_value()) {
|
||||||
|
// TODO: recalc this
|
||||||
this->nodes[next.value()].prev = prev;
|
this->nodes[next.value()].prev = prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -755,8 +746,11 @@ public:
|
||||||
ref->next.has_value() ? &this->nodes[ref->next.value()] : nullptr;
|
ref->next.has_value() ? &this->nodes[ref->next.value()] : nullptr;
|
||||||
Node *prev =
|
Node *prev =
|
||||||
ref->prev.has_value() ? &this->nodes[ref->prev.value()] : nullptr;
|
ref->prev.has_value() ? &this->nodes[ref->prev.value()] : nullptr;
|
||||||
|
|
||||||
|
// TODO: recalc this
|
||||||
prev->next = next != nullptr ? std::optional{next - &this->nodes[0]}
|
prev->next = next != nullptr ? std::optional{next - &this->nodes[0]}
|
||||||
: std::nullopt;
|
: std::nullopt;
|
||||||
|
// TODO: recalc this
|
||||||
next->prev = prev != nullptr ? std::optional{prev - &this->nodes[0]}
|
next->prev = prev != nullptr ? std::optional{prev - &this->nodes[0]}
|
||||||
: std::nullopt;
|
: std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue