diff --git a/Map.hpp b/Map.hpp index 49254d3..f649961 100644 --- a/Map.hpp +++ b/Map.hpp @@ -4,11 +4,9 @@ #include #include #include -#include -#include -#include #include #include +#include // everything is super interconnected so some forward declarations are needed at // various points @@ -32,11 +30,12 @@ Direction operator!(Direction dir) { } template struct BookKeeping { using Self = BookKeeping; - using ValueType = std::pair; + using ValueType = std::pair; + using Ptr = typename std::vector::iterator; friend class Map; Map &container; ValueType value; - typename std::list::iterator self; + Ptr self; Color color; // nullptr indicates empty Self *parent; @@ -45,6 +44,26 @@ template struct BookKeeping { Self *prev; Self *next; BookKeeping(Map &container) : container{container} {} + 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}, + prev{rhs.prev}, next{rhs.next} {} + // if pointing to different containers throws + BookKeeping &operator=(BookKeeping const &rhs) { + if (&this->container != &rhs.container) { + throw std::invalid_argument{"can only reassign Bookkeeping " + "values/iterators from the same map object"}; + } + this->value = rhs.value; + this->self = rhs.self; + this->color = rhs.color; + this->parent = rhs.parent; + this->left = rhs.left; + this->right = rhs.right; + this->prev = rhs.prev; + this->next = rhs.next; + return *this; + } // reference to a pointer because the alternatives were worse inline Self *&child(Direction dir) { switch (dir) { @@ -54,6 +73,8 @@ template struct BookKeeping { case Direction::Right: return right; break; + default: + assert(false); } } // this is root/P for this method @@ -87,7 +108,7 @@ template struct BookKeeping { G->left = S; } } else { - T->root = S; + T.root = S; } } }; @@ -95,7 +116,7 @@ template struct BookKeeping { // https://en.wikipedia.org/wiki/Red%E2%80%93black_tree template class Map { private: - using ValueType = std::pair; + using ValueType = std::pair; using Node = BookKeeping; using Map_T = Map; @@ -259,7 +280,7 @@ private: Node *root; Node *min; Node *max; - std::list nodes; + std::vector nodes; public: Map() : root{nullptr}, min{nullptr}, max{nullptr}, nodes{} {} @@ -295,7 +316,11 @@ public: // it here auto [parent, dir] = this->locate_slot(key); if (parent == nullptr) { - return this->end(); + if (this->root->value.first == key) { + return Iterator{root}; + } else { + return this->end(); + } } if (parent->child(dir) == nullptr) { return this->end(); @@ -449,13 +474,14 @@ public: // an iterator pointing to the element with the same key, and false. std::pair insert(const ValueType &val) { auto [parent, dir] = locate_slot(val.first); - bool ret = parent->child(dir) == nullptr; + bool ret = parent == nullptr || parent->child(dir) == nullptr; if (!ret) { return std::make_pair(Iterator{parent->child(dir)}, ret); } Node to_insert{*this}; to_insert.value = val; this->nodes.push_back(std::move(to_insert)); + this->nodes.back().self = (--this->nodes.end()); insert_helper(&nodes.back(), parent, dir); if (min == nullptr || val.first < min->value.first) { @@ -465,7 +491,7 @@ public: max = &nodes.back(); } - return std::make_pair(Iterator{&nodes.back()}, ret); + return std::make_pair(Iterator(&nodes.back()), ret); } template void insert(IT_T range_beg, IT_T range_end) { std::for_each(range_beg, range_end, @@ -562,7 +588,6 @@ private: public: // TODO: check that the way of reconnecting next and prev works void erase(Iterator pos) { - auto &container = pos.ref->container; // simple cases Node *ref = pos.ref; // 2 children @@ -593,15 +618,13 @@ public: // no children and root else if (ref->left == nullptr && ref->right == nullptr) { this->root = nullptr; - this->nodes.erase(ref->value); } // no children and red - else if (ref->left == nodes.end() && ref->right == nodes.end()) { + else if (ref->left == nullptr && ref->right == nullptr) { Node *next = ref->next; Node *prev = ref->prev; prev->next = next; next->prev = prev; - this->nodes.erase(ref->value); } // complicated case of black node with no kids else {