fixed some bugs

This commit is contained in:
Pagwin 2024-11-22 15:43:10 -05:00
parent b5b03e5fbe
commit f87ca7431d
No known key found for this signature in database
GPG key ID: 81137023740CA260

48
Map.hpp
View file

@ -35,7 +35,7 @@ template <typename Key_T, typename Mapped_T> struct BookKeeping {
friend class Map<Key_T, Mapped_T>; friend class Map<Key_T, Mapped_T>;
Map<Key_T, Mapped_T> &container; Map<Key_T, Mapped_T> &container;
ValueType value; ValueType value;
Ptr self; // Ptr self;
Color color; Color color;
// nullptr indicates empty // nullptr indicates empty
Self *parent; Self *parent;
@ -45,7 +45,7 @@ template <typename Key_T, typename Mapped_T> struct BookKeeping {
Self *next; Self *next;
BookKeeping(Map<Key_T, Mapped_T> &container) : container{container} {} BookKeeping(Map<Key_T, Mapped_T> &container) : container{container} {}
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},
prev{rhs.prev}, next{rhs.next} {} prev{rhs.prev}, next{rhs.next} {}
// if pointing to different containers throws // if pointing to different containers throws
@ -55,7 +55,7 @@ template <typename Key_T, typename Mapped_T> struct BookKeeping {
"values/iterators from the same map object"}; "values/iterators from the same map object"};
} }
this->value = rhs.value; this->value = rhs.value;
this->self = rhs.self; // this->self = rhs.self;
this->color = rhs.color; this->color = rhs.color;
this->parent = rhs.parent; this->parent = rhs.parent;
this->left = rhs.left; this->left = rhs.left;
@ -287,6 +287,9 @@ public:
Map(const Map &rhs) Map(const Map &rhs)
: root{rhs.root}, min{nullptr}, max{nullptr}, nodes{rhs.nodes} {} : root{rhs.root}, min{nullptr}, max{nullptr}, nodes{rhs.nodes} {}
Map &operator=(const Map &rhs) { Map &operator=(const Map &rhs) {
// TODO: fix this so all the pointers in all the bookkeeping nodes are
// updated in addition to root, min and max
assert(false);
this->root = rhs.root; this->root = rhs.root;
this->min = rhs.min; this->min = rhs.min;
this->max = rhs.max; this->max = rhs.max;
@ -316,7 +319,7 @@ public:
// it here // it here
auto [parent, dir] = this->locate_slot(key); auto [parent, dir] = this->locate_slot(key);
if (parent == nullptr) { if (parent == nullptr) {
if (this->root->value.first == key) { if (this->root != nullptr && this->root->value.first == key) {
return Iterator{root}; return Iterator{root};
} else { } else {
return this->end(); return this->end();
@ -330,9 +333,26 @@ public:
// implicit cast to ConstIterator from Iterator // implicit cast to ConstIterator from Iterator
ConstIterator find(const Key_T &key) const { return this->find(key); } ConstIterator find(const Key_T &key) const { return this->find(key); }
Mapped_T &at(const Key_T &key) { return (this->find(key))->second; } Mapped_T &at(const Key_T &key) {
const Mapped_T &at(const Key_T &key) const { return this->at(key); } auto ret = this->find(key);
Mapped_T &operator[](const Key_T &key) { return this->at(key); } if (ret == this->end()) {
throw std::out_of_range{"Key not in map"};
}
return ret->second;
}
const Mapped_T &at(const Key_T &key) const {
auto ret = this->find(key);
if (ret == this->end()) {
throw std::out_of_range{"Key not in map"};
}
return ret->second;
}
Mapped_T &operator[](const Key_T &key) {
Mapped_T v;
auto insert_val = std::make_pair(key, v);
auto [iter, key_no_exist] = this->insert(insert_val);
return iter->second;
}
private: private:
void handle_root_rotation(Node *grandparent, Node *parent, Node *inserting, void handle_root_rotation(Node *grandparent, Node *parent, Node *inserting,
@ -380,11 +400,13 @@ private:
to_insert->next = parent; to_insert->next = parent;
to_insert->prev = parent->prev; to_insert->prev = parent->prev;
parent->prev = to_insert; parent->prev = to_insert;
parent->left = to_insert;
break; break;
case Direction::Right: case Direction::Right:
to_insert->prev = parent; to_insert->prev = parent;
to_insert->next = parent->next; to_insert->next = parent->next;
parent->next = to_insert; parent->next = to_insert;
parent->right = to_insert;
break; break;
} }
@ -456,7 +478,7 @@ private:
Direction dir; Direction dir;
while (current != nullptr && current->value.first != key) { while (current != nullptr && current->value.first != key) {
parent = current; parent = current;
if (current->value.first < key) { if (key < current->value.first) {
dir = Direction::Left; dir = Direction::Left;
current = current->left; current = current->left;
} else { } else {
@ -481,14 +503,16 @@ public:
Node to_insert{*this}; Node to_insert{*this};
to_insert.value = val; to_insert.value = val;
this->nodes.push_back(std::move(to_insert)); this->nodes.push_back(std::move(to_insert));
this->nodes.back().self = (--this->nodes.end()); // this->nodes.back().self = (--this->nodes.end());
insert_helper(&nodes.back(), parent, dir); insert_helper(&nodes.back(), parent, dir);
if (min == nullptr || val.first < min->value.first) { if (min == nullptr || val.first < min->value.first) {
min = &nodes.back(); min = &nodes.back();
nodes.back().prev = nullptr;
} }
if (max == nullptr || val.first > max->value.first) { if (max == nullptr || val.first > max->value.first) {
max = &nodes.back(); max = &nodes.back();
nodes.back().next = nullptr;
} }
return std::make_pair(Iterator(&nodes.back()), ret); return std::make_pair(Iterator(&nodes.back()), ret);
@ -590,6 +614,12 @@ public:
void erase(Iterator pos) { void erase(Iterator pos) {
// simple cases // simple cases
Node *ref = pos.ref; Node *ref = pos.ref;
if (ref == this->min) {
this->min = ref->next;
}
if (ref == this->max) {
this->max = ref->prev;
}
// 2 children // 2 children
if (ref->left != nullptr && ref->right != nullptr) { if (ref->left != nullptr && ref->right != nullptr) {
Node *next = ref->next; Node *next = ref->next;