slowly working through given tests to get Map fully working in all functionality

This commit is contained in:
Pagwin 2024-11-25 16:25:47 -05:00
parent 315a200c9b
commit ce0f5f7ef0
No known key found for this signature in database
GPG key ID: 81137023740CA260
2 changed files with 125 additions and 137 deletions

105
Map.hpp
View file

@ -4,7 +4,6 @@
// uncomment on submission/performance test
// #define NDEBUG
#include <cassert>
#include <iostream>
#include <memory>
#include <optional>
#include <stdexcept>
@ -32,8 +31,8 @@ template <typename Key_T, typename Mapped_T> class Map {
struct Node {
int valid = 0x13371337;
Node *parent;
internal_ValueType val;
Node *parent = nullptr;
std::unique_ptr<internal_ValueType> val;
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
Color color;
@ -41,13 +40,14 @@ template <typename Key_T, typename Mapped_T> class Map {
Node *next;
Map *map;
Node(internal_ValueType val, Map *map)
: parent{nullptr}, val{val}, left{}, right{}, color{Color::Red},
prev{nullptr}, next{nullptr}, map{map} {}
: parent{nullptr}, val{new internal_ValueType{val}}, left{}, right{},
color{Color::Red}, prev{nullptr}, next{nullptr}, map{map} {}
Node(const Node &rhs)
: parent{nullptr}, val{rhs.val},
left{std::make_unique<Node>(*rhs.left)},
right{std::make_unique<Node>(*rhs.right)}, color{rhs.color},
prev{nullptr}, next{nullptr}, map{rhs.map} {
: parent{nullptr},
val{rhs.val ? new internal_ValueType{*rhs.val} : nullptr},
left{rhs.left ? std::make_unique<Node>(*rhs.left) : nullptr},
right{rhs.right ? std::make_unique<Node>(*rhs.right) : nullptr},
color{rhs.color}, prev{nullptr}, next{nullptr}, map{rhs.map} {
this->valid = 0x13371337;
if (this->left) {
@ -64,11 +64,7 @@ template <typename Key_T, typename Mapped_T> class Map {
: parent{nullptr}, val{std::move(rhs.val)}, left{std::move(rhs.left)},
right{std::move(rhs.right)}, color{rhs.color}, prev{nullptr},
next{nullptr}, map{rhs.map} {
// TODO: remove on finish
if (rhs.valid != 0x13371337) {
std::cerr << "(" << rhs.val.first << ")" << std::endl;
}
rhs.valid = 0;
this->valid = 0x13371337;
@ -88,9 +84,12 @@ template <typename Key_T, typename Mapped_T> class Map {
// to a rotation where parent can get wonky
// this->parent
this->val = rhs.val;
this->left = std::make_unique<Node>(*rhs.left);
this->right = std::make_unique<Node>(*rhs.right);
this->val =
rhs.val ? std::unique_ptr<internal_ValueType>{new internal_ValueType{
*rhs.val}}
: nullptr;
this->left = rhs.left ? std::make_unique<Node>(*rhs.left) : nullptr;
this->right = rhs.right ? std::make_unique<Node>(*rhs.right) : nullptr;
this->color = rhs.color;
this->valid = 0x13371337;
@ -110,7 +109,7 @@ template <typename Key_T, typename Mapped_T> class Map {
// retain parent as is, common case is the copy or move is happening due
// to a rotation where parent can get wonky
// this->parent
this->val = rhs.val;
this->val = std::move(rhs.val);
this->left = std::move(rhs.left);
this->right = std::move(rhs.right);
this->color = rhs.color;
@ -532,8 +531,26 @@ public:
};
Map() : root{}, _size{0} {}
Map(const Map &rhs) : root{rhs.root}, _size{rhs._size} {}
Map(Map &&rhs) : root{std::move(rhs.root)}, _size{rhs._size} {}
Map(const Map &rhs) : root{rhs.root}, _size{rhs._size} {
this->min = &this->root.value();
this->max = &this->root.value();
while (min->left) {
min = min->left.get();
}
while (min->right) {
min = min->left.get();
}
}
Map(Map &&rhs) : root{std::move(rhs.root)}, _size{rhs._size} {
this->min = &this->root.value();
this->max = &this->root.value();
while (min->left) {
min = min->left.get();
}
while (min->right) {
min = min->left.get();
}
}
Map &operator=(const Map &rhs) {
this->root = rhs.root;
this->_size = rhs._size;
@ -550,8 +567,8 @@ public:
void check() {
assert(!this->root || this->root.value().color == Color::Black);
}
std::size_t size() { return this->_size; }
bool empty() { return this->size() == 0; }
std::size_t size() const { return this->_size; }
bool empty() const { return this->size() == 0; }
private:
// private helpers
@ -604,53 +621,28 @@ private:
Direction ret_dir;
// map is empty
if (!this->root.has_value()) {
if constexpr (trace) {
std::cerr << "(map empty)" << std::endl;
}
return std::make_pair(nullptr, ret_dir);
}
if constexpr (trace) {
std::cerr << "root";
}
// value is in root
if (this->root.value().val.first == key) {
if constexpr (trace) {
std::cerr << "->found" << std::endl;
}
if (this->root.value().val->first == key) {
return std::make_pair(nullptr, ret_dir);
}
ret_parent = &this->root.value();
if (key < ret_parent->val.first) {
if constexpr (trace) {
std::cerr << "->left";
}
if (key < ret_parent->val->first) {
ret_dir = Direction::Left;
} else {
if constexpr (trace) {
std::cerr << "->right";
}
ret_dir = Direction::Right;
}
while (ret_parent->child(ret_dir) &&
ret_parent->child(ret_dir)->val.first != key) {
!(ret_parent->child(ret_dir)->val->first == key)) {
ret_parent = ret_parent->child(ret_dir);
if (key < ret_parent->val.first) {
if constexpr (trace) {
std::cerr << "->left";
}
if (key < ret_parent->val->first) {
ret_dir = Direction::Left;
} else {
if constexpr (trace) {
std::cerr << "->right";
}
ret_dir = Direction::Right;
}
}
if constexpr (trace) {
std::cerr << "->found" << std::endl;
}
return std::make_pair(ret_parent, ret_dir);
}
void hard_erase(Node *n) {
@ -754,7 +746,7 @@ private:
// 2 children
if (erasing->left && erasing->right) {
Node *succ = erasing->next;
erasing->val = succ->val;
erasing->val = std::move(succ->val);
this->core_erase(succ);
}
// 1 child
@ -800,7 +792,7 @@ public:
auto [parent, dir] = locate(key);
if (parent == nullptr) {
if (this->root.has_value()) {
if (this->root.value().val.first == key) {
if (this->root.value().val->first == key) {
return Iterator{&this->root.value()};
}
}
@ -815,7 +807,7 @@ public:
auto [parent, dir] = locate(key);
if (parent == nullptr) {
if (this->root.has_value()) {
if (this->root.value().val.first == key) {
if (this->root.value().val->first == key) {
return Iterator{const_cast<Node *>(&this->root.value())};
}
}
@ -881,7 +873,7 @@ public:
if (core_erase(pos.underlying)) {
pos.underlying->restore_ordering();
} else {
if (before != nullptr) {
if (before != nullptr && before->valid == 0x13371337) {
before->next = before->calc_succ();
if (before->next != nullptr) {
before->next->prev = before;
@ -889,7 +881,7 @@ public:
} else {
this->min = after;
}
if (after != nullptr) {
if (after != nullptr && after->valid == 0x13371337) {
after->prev = after->calc_pred();
if (after->prev != nullptr) {
after->prev->next = after;
@ -925,7 +917,7 @@ public:
if (ret == this->end()) {
throw std::out_of_range{"key not in map"};
}
return (*ret).first;
return (*ret).second;
}
Mapped_T &operator[](const Key_T &key) {
this->insert({key, {}});
@ -939,7 +931,6 @@ public:
}
}
void erase(const Key_T &key) { this->erase(this->find(key)); }
// TODO:
friend bool operator==(const Map &lhs, const Map &rhs) {
if (lhs.size() != rhs.size()) {
return false;

View file

@ -4,25 +4,23 @@
// basically an int wrapper
class MyKeyType {
private:
private:
int val;
public:
//not default constructable, not copy assignable, not move assignable
public:
// not default constructable, not copy assignable, not move assignable
MyKeyType() = delete;
MyKeyType& operator=(const MyKeyType&) = delete;
MyKeyType& operator=(MyKeyType&&) = delete;
MyKeyType &operator=(const MyKeyType &) = delete;
MyKeyType &operator=(MyKeyType &&) = delete;
// copy constructable and move assignable
MyKeyType(MyKeyType&&) = default;
MyKeyType(const MyKeyType&) = default;
MyKeyType(MyKeyType &&) = default;
MyKeyType(const MyKeyType &) = default;
~MyKeyType() = default;
MyKeyType(int i) : val(i) { }
MyKeyType(int i) : val(i) {}
bool operator<(const MyKeyType& other) const {
return this->val < other.val;
}
bool operator<(const MyKeyType &other) const { return this->val < other.val; }
bool operator==(const MyKeyType &other) const {
return this->val == other.val;
@ -31,21 +29,21 @@ class MyKeyType {
// same as keytype except no operator<
class MyValueType {
private:
private:
int val;
public:
//not default constructable, not copy assignable, not move assignable
public:
// not default constructable, not copy assignable, not move assignable
MyValueType() = delete;
MyValueType& operator=(const MyValueType&) = delete;
MyValueType& operator=(MyValueType&&) = delete;
MyValueType &operator=(const MyValueType &) = delete;
MyValueType &operator=(MyValueType &&) = delete;
// copy constructable and move assignable
MyValueType(MyValueType&&) = default;
MyValueType(const MyValueType&) = default;
MyValueType(MyValueType &&) = default;
MyValueType(const MyValueType &) = default;
~MyValueType() = default;
MyValueType(int i) : val(i) { }
MyValueType(int i) : val(i) {}
bool operator==(const MyValueType &other) const {
return this->val == other.val;
@ -54,39 +52,39 @@ class MyValueType {
class MyDefaultConstructible {
friend bool operator<(const MyDefaultConstructible &o1, const MyDefaultConstructible &o2) {
friend bool operator<(const MyDefaultConstructible &o1,
const MyDefaultConstructible &o2) {
return o1.val < o2.val;
}
private:
private:
int val = 0;
public:
public:
// not copy assignable, not move assignable
MyDefaultConstructible& operator=(const MyDefaultConstructible&) = delete;
MyDefaultConstructible& operator=(MyDefaultConstructible&&) = delete;
MyDefaultConstructible &operator=(const MyDefaultConstructible &) = delete;
MyDefaultConstructible &operator=(MyDefaultConstructible &&) = delete;
// default constructable, copy constructable and move assignable
MyDefaultConstructible() = default;
MyDefaultConstructible(MyDefaultConstructible&&) = default;
MyDefaultConstructible(const MyDefaultConstructible&) = default;
MyDefaultConstructible(MyDefaultConstructible &&) = default;
MyDefaultConstructible(const MyDefaultConstructible &) = default;
~MyDefaultConstructible() = default;
MyDefaultConstructible(int i) : val(i) { }
MyDefaultConstructible(int i) : val(i) {}
bool operator==(const MyDefaultConstructible &other) const {
return this->val == other.val;
}
};
class MyAssignable {
private:
private:
int val = 0;
public:
public:
MyAssignable() = default;
MyAssignable(int i) : val(i) { }
MyAssignable(int i) : val(i) {}
bool operator==(const MyAssignable &other) const {
return this->val == other.val;
}
@ -96,7 +94,6 @@ class MyAssignable {
// just the ones called
template class cs440::Map<MyKeyType, MyDefaultConstructible>;
int main() {
cs440::Map<MyKeyType, MyValueType> m{{3, 5}};
m.insert({{2}, {3}});
@ -116,7 +113,7 @@ int main() {
cs440::Map<MyKeyType, MyAssignable> m3{{6, 7}};
m3[20] = {5}; // move assign
MyAssignable ma{1};
m3[10] = ma; //copy assign
m3[10] = ma; // copy assign
return 0;
}