committing before I redo red-black deletion of black leaf
This commit is contained in:
parent
a0ce38e2ee
commit
f73c68a980
1 changed files with 90 additions and 49 deletions
139
Map.hpp
139
Map.hpp
|
@ -48,7 +48,6 @@ 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) {
|
||||||
|
@ -62,7 +61,6 @@ 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;
|
||||||
|
@ -353,6 +351,55 @@ private:
|
||||||
std::vector<Node> nodes;
|
std::vector<Node> nodes;
|
||||||
std::size_t size_diff;
|
std::size_t size_diff;
|
||||||
|
|
||||||
|
std::optional<std::size_t> 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<std::size_t> 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:
|
public:
|
||||||
Map()
|
Map()
|
||||||
: root{std::nullopt}, min{std::nullopt}, max{std::nullopt}, nodes{},
|
: root{std::nullopt}, min{std::nullopt}, max{std::nullopt}, nodes{},
|
||||||
|
@ -473,18 +520,9 @@ 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()].prev = this->nodes[parent.value()].prev;
|
|
||||||
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()].next = this->nodes[parent.value()].next;
|
|
||||||
// TODO: recalc this
|
|
||||||
this->nodes[parent.value()].next = to_insert;
|
|
||||||
this->nodes[parent.value()].right = to_insert;
|
this->nodes[parent.value()].right = to_insert;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -585,14 +623,21 @@ public:
|
||||||
if (min == std::nullopt ||
|
if (min == std::nullopt ||
|
||||||
val.first < this->nodes[min.value()].value.first) {
|
val.first < this->nodes[min.value()].value.first) {
|
||||||
min = nodes.size() - 1;
|
min = nodes.size() - 1;
|
||||||
nodes.back().prev = std::nullopt;
|
|
||||||
}
|
}
|
||||||
if (max == std::nullopt ||
|
if (max == std::nullopt ||
|
||||||
val.first > this->nodes[max.value()].value.first) {
|
val.first > this->nodes[max.value()].value.first) {
|
||||||
max = nodes.size() - 1;
|
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);
|
return std::make_pair(Iterator(*this, nodes.size() - 1), ret);
|
||||||
}
|
}
|
||||||
template <typename IT_T> void insert(IT_T range_beg, IT_T range_end) {
|
template <typename IT_T> void insert(IT_T range_beg, IT_T range_end) {
|
||||||
|
@ -688,7 +733,6 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// TODO: check that the way of reconnecting next and prev works
|
|
||||||
void erase(Iterator pos) {
|
void erase(Iterator pos) {
|
||||||
this->size_diff++;
|
this->size_diff++;
|
||||||
// simple cases
|
// simple cases
|
||||||
|
@ -703,61 +747,58 @@ 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 = this->nodes[next.value()];
|
*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});
|
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
|
if (ref->par()->l() == ref) {
|
||||||
Ref_T next = ref->next;
|
ref->par()->set_l(ref->l());
|
||||||
Ref_T prev = ref->prev;
|
} else {
|
||||||
*ref = *ref->l();
|
ref->par()->set_r(ref->l());
|
||||||
this->nodes[prev.value()].next = next;
|
}
|
||||||
this->nodes[next.value()].prev = prev;
|
if (ref->color == Color::Black) {
|
||||||
|
ref->l()->color = Color::Black;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 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
|
if (ref->par()->l() == ref) {
|
||||||
Ref_T next = ref->next;
|
ref->par()->set_l(ref->r());
|
||||||
Ref_T prev = ref->prev;
|
} else {
|
||||||
*ref = *ref->r();
|
ref->par()->set_r(ref->r());
|
||||||
if (prev.has_value()) {
|
|
||||||
// TODO: recalc this
|
|
||||||
this->nodes[prev.value()].next = next;
|
|
||||||
}
|
}
|
||||||
if (next.has_value()) {
|
if (ref->color == Color::Black) {
|
||||||
// TODO: recalc this
|
ref->r()->color = Color::Black;
|
||||||
this->nodes[next.value()].prev = prev;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// no children and root
|
// 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;
|
this->root = std::nullopt;
|
||||||
}
|
}
|
||||||
// no children and red
|
// no children and red
|
||||||
else if (ref->l() == nullptr && ref->r() == nullptr) {
|
else if (ref->color == Color::Red && ref->l() == nullptr &&
|
||||||
Node *next =
|
ref->r() == nullptr) {
|
||||||
ref->next.has_value() ? &this->nodes[ref->next.value()] : nullptr;
|
if (ref->parent.has_value()) {
|
||||||
Node *prev =
|
if (this->nodes[ref->parent.value()].right == pos.ref.value()) {
|
||||||
ref->prev.has_value() ? &this->nodes[ref->prev.value()] : nullptr;
|
this->nodes[ref->parent.value()].right = std::nullopt;
|
||||||
|
} else {
|
||||||
// TODO: recalc this
|
this->nodes[ref->parent.value()].left = std::nullopt;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
// complicated case of black node with no kids
|
// complicated case of black node with no kids
|
||||||
else {
|
else {
|
||||||
this->complex_erase(pos);
|
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 erase(const Key_T &key) { this->erase(this->find(key)); }
|
||||||
void clear() {
|
void clear() {
|
||||||
|
|
Loading…
Reference in a new issue