did most of the misc stuff just need < and ==
This commit is contained in:
parent
27409cc0b0
commit
09d2323cbf
2 changed files with 275 additions and 48 deletions
291
Map.hpp
291
Map.hpp
|
@ -7,6 +7,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <stdexcept>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
namespace cs440 {
|
namespace cs440 {
|
||||||
// universal type defs here
|
// universal type defs here
|
||||||
|
@ -47,12 +48,17 @@ template <typename Key_T, typename Mapped_T> class Map {
|
||||||
left{std::make_unique<Node>(*rhs.left)},
|
left{std::make_unique<Node>(*rhs.left)},
|
||||||
right{std::make_unique<Node>(*rhs.right)}, color{rhs.color},
|
right{std::make_unique<Node>(*rhs.right)}, color{rhs.color},
|
||||||
prev{nullptr}, next{nullptr}, map{rhs.map} {
|
prev{nullptr}, next{nullptr}, map{rhs.map} {
|
||||||
|
this->valid = 0x13371337;
|
||||||
|
|
||||||
if (this->left) {
|
if (this->left) {
|
||||||
this->left->parent = this;
|
this->left->parent = this;
|
||||||
}
|
}
|
||||||
if (this->right) {
|
if (this->right) {
|
||||||
this->right->parent = this;
|
this->right->parent = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->next = rhs.next;
|
||||||
|
this->prev = rhs.prev;
|
||||||
}
|
}
|
||||||
Node(Node &&rhs)
|
Node(Node &&rhs)
|
||||||
: parent{nullptr}, val{std::move(rhs.val)}, left{std::move(rhs.left)},
|
: parent{nullptr}, val{std::move(rhs.val)}, left{std::move(rhs.left)},
|
||||||
|
@ -72,17 +78,22 @@ template <typename Key_T, typename Mapped_T> class Map {
|
||||||
if (this->right) {
|
if (this->right) {
|
||||||
this->right->parent = this;
|
this->right->parent = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->next = rhs.next;
|
||||||
|
this->prev = rhs.prev;
|
||||||
}
|
}
|
||||||
~Node() {}
|
~Node() {}
|
||||||
Node &operator=(const Node &rhs) {
|
Node &operator=(const Node &rhs) {
|
||||||
// retain parent as is, common case is the copy or move is happening due
|
// retain parent as is, common case is the copy or move is happening due
|
||||||
// to a rotation where parent can get wonky
|
// to a rotation where parent can get wonky
|
||||||
// this->parent
|
// this->parent
|
||||||
|
|
||||||
this->val = rhs.val;
|
this->val = rhs.val;
|
||||||
this->left = std::make_unique<Node>(*rhs.left);
|
this->left = std::make_unique<Node>(*rhs.left);
|
||||||
this->right = std::make_unique<Node>(*rhs.right);
|
this->right = std::make_unique<Node>(*rhs.right);
|
||||||
this->color = rhs.color;
|
this->color = rhs.color;
|
||||||
this->valid = 0x13371337;
|
this->valid = 0x13371337;
|
||||||
|
|
||||||
if (this->left) {
|
if (this->left) {
|
||||||
this->left->parent = this;
|
this->left->parent = this;
|
||||||
this->left->restore_ordering();
|
this->left->restore_ordering();
|
||||||
|
@ -91,7 +102,7 @@ template <typename Key_T, typename Mapped_T> class Map {
|
||||||
this->right->parent = this;
|
this->right->parent = this;
|
||||||
this->right->restore_ordering();
|
this->right->restore_ordering();
|
||||||
}
|
}
|
||||||
|
this->restore_ordering();
|
||||||
this->map = rhs.map;
|
this->map = rhs.map;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -113,6 +124,7 @@ template <typename Key_T, typename Mapped_T> class Map {
|
||||||
this->right->parent = this;
|
this->right->parent = this;
|
||||||
this->right->restore_ordering();
|
this->right->restore_ordering();
|
||||||
}
|
}
|
||||||
|
this->restore_ordering();
|
||||||
this->map = rhs.map;
|
this->map = rhs.map;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -126,6 +138,16 @@ template <typename Key_T, typename Mapped_T> class Map {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Node const *child(Direction dir) const {
|
||||||
|
switch (dir) {
|
||||||
|
case Direction::Left:
|
||||||
|
return this->left.get();
|
||||||
|
case Direction::Right:
|
||||||
|
return this->right.get();
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
std::unique_ptr<Node> uchild(Direction dir) {
|
std::unique_ptr<Node> uchild(Direction dir) {
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case Direction::Left:
|
case Direction::Left:
|
||||||
|
@ -174,6 +196,8 @@ template <typename Key_T, typename Mapped_T> class Map {
|
||||||
}
|
}
|
||||||
void erase_child(Node *n) { this->erase_child(this->which_child(n)); }
|
void erase_child(Node *n) { this->erase_child(this->which_child(n)); }
|
||||||
void erase_child(Direction dir) {
|
void erase_child(Direction dir) {
|
||||||
|
bool minmax = this->child(dir) == this->map->min ||
|
||||||
|
this->child(dir) == this->map->max;
|
||||||
// bringing ownership to this function scope so Deleter gets called at end
|
// bringing ownership to this function scope so Deleter gets called at end
|
||||||
// of function and we can do reordering things
|
// of function and we can do reordering things
|
||||||
std::unique_ptr<Node> dropping;
|
std::unique_ptr<Node> dropping;
|
||||||
|
@ -197,6 +221,18 @@ template <typename Key_T, typename Mapped_T> class Map {
|
||||||
if (dropping->next != nullptr) {
|
if (dropping->next != nullptr) {
|
||||||
dropping->next->prev = dropping->prev;
|
dropping->next->prev = dropping->prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (minmax) {
|
||||||
|
switch (dir) {
|
||||||
|
case Direction::Left:
|
||||||
|
this->map->min = this;
|
||||||
|
break;
|
||||||
|
case Direction::Right:
|
||||||
|
this->map->max = this;
|
||||||
|
break;
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void restore_ordering() {
|
void restore_ordering() {
|
||||||
this->prev = this->calc_pred();
|
this->prev = this->calc_pred();
|
||||||
|
@ -344,6 +380,8 @@ template <typename Key_T, typename Mapped_T> class Map {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
friend Node;
|
friend Node;
|
||||||
|
class ConstIterator;
|
||||||
|
class ReverseIterator;
|
||||||
// public type definitions
|
// public type definitions
|
||||||
class Iterator {
|
class Iterator {
|
||||||
Node *underlying;
|
Node *underlying;
|
||||||
|
@ -353,34 +391,146 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
friend Map;
|
friend Map;
|
||||||
|
friend ConstIterator;
|
||||||
|
friend ReverseIterator;
|
||||||
Iterator() = delete;
|
Iterator() = delete;
|
||||||
void check() {
|
Iterator(const Iterator &rhs) = default;
|
||||||
|
Iterator &operator=(const Iterator &) = default;
|
||||||
|
~Iterator() = default;
|
||||||
|
// precrement
|
||||||
|
Iterator &operator++() {
|
||||||
if (this->underlying == nullptr) {
|
if (this->underlying == nullptr) {
|
||||||
return;
|
this->underlying = this->store;
|
||||||
|
this->store = nullptr;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
if (this->underlying->parent) {
|
if (this->underlying->next == nullptr) {
|
||||||
switch (this->underlying->parent->which_child(this->underlying)) {
|
this->store = this->underlying;
|
||||||
case Direction::Left:
|
|
||||||
assert(this->underlying->val.first <
|
|
||||||
this->underlying->parent->val.first);
|
|
||||||
break;
|
|
||||||
case Direction::Right:
|
|
||||||
assert(this->underlying->val.first >
|
|
||||||
this->underlying->parent->val.first);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
}
|
||||||
|
this->underlying = this->underlying->next;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
if (this->underlying->right) {
|
// postcrement
|
||||||
assert(this->underlying->right->val.first >
|
Iterator operator++(int) {
|
||||||
this->underlying->val.first);
|
auto copy = *this;
|
||||||
|
this->operator++();
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
if (this->underlying->left) {
|
|
||||||
assert(this->underlying->left->val.first < this->underlying->val.first);
|
// precrement
|
||||||
|
Iterator &operator--() {
|
||||||
|
if (this->underlying == nullptr) {
|
||||||
|
this->underlying = this->store;
|
||||||
|
this->store = nullptr;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
if (this->underlying->prev == nullptr) {
|
||||||
|
this->store = this->underlying;
|
||||||
|
}
|
||||||
|
this->underlying = this->underlying->prev;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
// postcrement
|
||||||
|
Iterator operator--(int) {
|
||||||
|
auto copy = *this;
|
||||||
|
this->operator--();
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType &operator*() const {
|
||||||
|
ValueType *ret = (ValueType *)(&this->underlying->val);
|
||||||
|
return *ret;
|
||||||
|
}
|
||||||
|
ValueType *operator->() const { return &this->operator*(); }
|
||||||
|
friend bool operator==(const Iterator &lhs, const Iterator &rhs) {
|
||||||
|
return lhs.underlying == rhs.underlying;
|
||||||
|
}
|
||||||
|
friend bool operator!=(const Iterator &lhs, const Iterator &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
class ConstIterator {
|
||||||
|
Iterator underlying;
|
||||||
|
|
||||||
|
public:
|
||||||
|
friend Map;
|
||||||
|
ConstIterator() = delete;
|
||||||
|
ConstIterator(const Iterator &underlying) : underlying{underlying} {}
|
||||||
|
ConstIterator(const ConstIterator &rhs) = default;
|
||||||
|
ConstIterator &operator=(const ConstIterator &) = default;
|
||||||
|
~ConstIterator() = default;
|
||||||
|
ConstIterator &operator++() {
|
||||||
|
++underlying;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ConstIterator operator++(int) {
|
||||||
|
auto copy = *this;
|
||||||
|
this->operator++();
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
ConstIterator &operator--() {
|
||||||
|
--underlying;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ConstIterator operator--(int) {
|
||||||
|
auto copy = *this;
|
||||||
|
this->operator--();
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
const ValueType &operator*() const { return this->underlying.operator*(); }
|
||||||
|
const ValueType *operator->() const { return &this->operator*(); }
|
||||||
|
|
||||||
|
friend bool operator==(const ConstIterator &lhs, const ConstIterator &rhs) {
|
||||||
|
return lhs.underlying == rhs.underlying;
|
||||||
|
}
|
||||||
|
friend bool operator!=(const ConstIterator &lhs, const ConstIterator &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
friend bool operator==(const Iterator &lhs, const ConstIterator &rhs) {
|
||||||
|
return lhs == rhs.underlying;
|
||||||
|
}
|
||||||
|
friend bool operator!=(const Iterator &lhs, const ConstIterator &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
friend bool operator==(const ConstIterator &lhs, const Iterator &rhs) {
|
||||||
|
return lhs.underlying == rhs;
|
||||||
|
}
|
||||||
|
friend bool operator!=(const ConstIterator &lhs, const Iterator &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class ReverseIterator {
|
||||||
|
Iterator underlying;
|
||||||
|
ReverseIterator(const Iterator &underlying) : underlying{underlying} {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
friend Map;
|
||||||
|
ReverseIterator() = delete;
|
||||||
|
ReverseIterator(const ReverseIterator &) = default;
|
||||||
|
~ReverseIterator() = default;
|
||||||
|
ReverseIterator &operator=(const ReverseIterator &) = default;
|
||||||
|
ReverseIterator &operator++() {
|
||||||
|
--underlying;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ReverseIterator operator++(int) {
|
||||||
|
auto copy = *this;
|
||||||
|
this->operator++();
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
ReverseIterator &operator--() {
|
||||||
|
++underlying;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ReverseIterator operator--(int) {
|
||||||
|
auto copy = *this;
|
||||||
|
this->operator++();
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
const ValueType &operator*() const { return this->underlying.operator*(); }
|
||||||
|
const ValueType *operator->() const { return &this->operator*(); }
|
||||||
|
};
|
||||||
|
|
||||||
Map() : root{}, _size{0} {}
|
Map() : root{}, _size{0} {}
|
||||||
Map(const Map &rhs) : root{rhs.root}, _size{rhs._size} {}
|
Map(const Map &rhs) : root{rhs.root}, _size{rhs._size} {}
|
||||||
Map(Map &&rhs) : root{std::move(rhs.root)}, _size{rhs._size} {}
|
Map(Map &&rhs) : root{std::move(rhs.root)}, _size{rhs._size} {}
|
||||||
|
@ -394,10 +544,14 @@ public:
|
||||||
this->_size = rhs._size;
|
this->_size = rhs._size;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
Map(std::initializer_list<std::pair<const Key_T, Mapped_T>> items) : Map{} {
|
||||||
|
this->insert(items.begin(), items.end());
|
||||||
|
}
|
||||||
void check() {
|
void check() {
|
||||||
assert(!this->root || this->root.value().color == Color::Black);
|
assert(!this->root || this->root.value().color == Color::Black);
|
||||||
}
|
}
|
||||||
std::size_t size() { return this->_size; }
|
std::size_t size() { return this->_size; }
|
||||||
|
bool empty() { return this->size() == 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// private helpers
|
// private helpers
|
||||||
|
@ -421,18 +575,32 @@ private:
|
||||||
if (old_root->right) {
|
if (old_root->right) {
|
||||||
old_root->right->parent = old_root.get();
|
old_root->right->parent = old_root.get();
|
||||||
}
|
}
|
||||||
|
if (old_root->next) {
|
||||||
|
old_root->next->prev = old_root.get();
|
||||||
|
}
|
||||||
|
if (old_root->prev) {
|
||||||
|
old_root->prev->next = old_root.get();
|
||||||
|
}
|
||||||
|
|
||||||
root.value().set_child(dir, std::move(old_root));
|
root.value().set_child(dir, std::move(old_root));
|
||||||
|
root.value().child(dir)->restore_ordering();
|
||||||
|
|
||||||
if (root.value().left) {
|
if (root.value().left) {
|
||||||
root.value().left->parent = &root.value();
|
root.value().left->parent = &root.value();
|
||||||
|
if (min == &root.value()) {
|
||||||
|
min = root.value().left.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (root.value().right) {
|
if (root.value().right) {
|
||||||
root.value().right->parent = &root.value();
|
root.value().right->parent = &root.value();
|
||||||
|
if (max == &root.value()) {
|
||||||
|
max = root.value().right.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <bool trace = false>
|
template <bool trace = false>
|
||||||
std::pair<Node *, Direction> locate(const Key_T &key) {
|
std::pair<Node const *, Direction> locate(const Key_T &key) const {
|
||||||
Node *ret_parent;
|
Node const *ret_parent;
|
||||||
Direction ret_dir;
|
Direction ret_dir;
|
||||||
// map is empty
|
// map is empty
|
||||||
if (!this->root.has_value()) {
|
if (!this->root.has_value()) {
|
||||||
|
@ -639,22 +807,22 @@ public:
|
||||||
return this->end();
|
return this->end();
|
||||||
}
|
}
|
||||||
if (parent->child(dir) != nullptr) {
|
if (parent->child(dir) != nullptr) {
|
||||||
return Iterator{parent->child(dir), nullptr};
|
return Iterator{const_cast<Node *>(parent->child(dir)), nullptr};
|
||||||
}
|
}
|
||||||
return this->end();
|
return this->end();
|
||||||
}
|
}
|
||||||
Iterator find_trace(const Key_T &key) {
|
ConstIterator find(const Key_T &key) const {
|
||||||
auto [parent, dir] = locate<true>(key);
|
auto [parent, dir] = locate(key);
|
||||||
if (parent == nullptr) {
|
if (parent == nullptr) {
|
||||||
if (this->root.has_value()) {
|
if (this->root.has_value()) {
|
||||||
if (this->root.value().val.first == key) {
|
if (this->root.value().val.first == key) {
|
||||||
return Iterator{&this->root.value()};
|
return Iterator{const_cast<Node *>(&this->root.value())};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this->end();
|
return this->end();
|
||||||
}
|
}
|
||||||
if (parent->child(dir) != nullptr) {
|
if (parent->child(dir) != nullptr) {
|
||||||
return Iterator{parent->child(dir), nullptr};
|
return Iterator{const_cast<Node *>(parent->child(dir)), nullptr};
|
||||||
}
|
}
|
||||||
return this->end();
|
return this->end();
|
||||||
}
|
}
|
||||||
|
@ -671,6 +839,9 @@ public:
|
||||||
} else {
|
} else {
|
||||||
this->root = Node{val, this};
|
this->root = Node{val, this};
|
||||||
this->root.value().color = Color::Black;
|
this->root.value().color = Color::Black;
|
||||||
|
this->min = &this->root.value();
|
||||||
|
this->max = &this->root.value();
|
||||||
|
this->_size++;
|
||||||
return std::make_pair(Iterator{&root.value()}, true);
|
return std::make_pair(Iterator{&root.value()}, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -678,21 +849,35 @@ public:
|
||||||
// non-root node
|
// non-root node
|
||||||
if (parent->child(dir)) {
|
if (parent->child(dir)) {
|
||||||
// node already present
|
// node already present
|
||||||
return std::make_pair(Iterator{parent->child(dir)}, false);
|
return std::make_pair(Iterator{const_cast<Node *>(parent->child(dir))},
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to insert non-root node
|
// need to insert non-root node
|
||||||
Node *new_node =
|
Map *m = const_cast<Map *>(this);
|
||||||
parent->set_child(dir, std::make_unique<Node>(Node{val, this})).get();
|
Node *new_node = const_cast<Node *>(parent)
|
||||||
|
->set_child(dir, std::make_unique<Node>(Node{val, m}))
|
||||||
|
.get();
|
||||||
new_node->restore_red_black_insert(dir);
|
new_node->restore_red_black_insert(dir);
|
||||||
|
|
||||||
new_node->restore_ordering();
|
new_node->restore_ordering();
|
||||||
|
if (this->min == parent && dir == Direction::Left) {
|
||||||
|
this->min = new_node;
|
||||||
|
}
|
||||||
|
if (this->max == parent && dir == Direction::Right) {
|
||||||
|
this->max = new_node;
|
||||||
|
}
|
||||||
|
this->_size++;
|
||||||
return std::make_pair(Iterator{new_node}, true);
|
return std::make_pair(Iterator{new_node}, true);
|
||||||
}
|
}
|
||||||
void erase(Iterator pos) {
|
void erase(Iterator pos) {
|
||||||
|
if (pos.underlying == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->_size--;
|
||||||
|
|
||||||
Node *before = pos.underlying->prev;
|
Node *before = pos.underlying->prev;
|
||||||
Node *after = pos.underlying->next;
|
Node *after = pos.underlying->next;
|
||||||
|
|
||||||
if (core_erase(pos.underlying)) {
|
if (core_erase(pos.underlying)) {
|
||||||
pos.underlying->restore_ordering();
|
pos.underlying->restore_ordering();
|
||||||
} else {
|
} else {
|
||||||
|
@ -701,12 +886,16 @@ public:
|
||||||
if (before->next != nullptr) {
|
if (before->next != nullptr) {
|
||||||
before->next->prev = before;
|
before->next->prev = before;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this->min = after;
|
||||||
}
|
}
|
||||||
if (after != nullptr) {
|
if (after != nullptr) {
|
||||||
after->prev = after->calc_pred();
|
after->prev = after->calc_pred();
|
||||||
if (after->prev != nullptr) {
|
if (after->prev != nullptr) {
|
||||||
after->prev->next = after;
|
after->prev->next = after;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this->max = before;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -714,6 +903,46 @@ public:
|
||||||
// baseline iterator creation
|
// baseline iterator creation
|
||||||
Iterator begin() { return Iterator{min, nullptr}; }
|
Iterator begin() { return Iterator{min, nullptr}; }
|
||||||
Iterator end() { return Iterator{nullptr, max}; }
|
Iterator end() { return Iterator{nullptr, max}; }
|
||||||
|
ConstIterator begin() const { return Iterator{min, nullptr}; }
|
||||||
|
ConstIterator end() const { return Iterator{nullptr, max}; }
|
||||||
|
ReverseIterator rbegin() { return Iterator{max, nullptr}; }
|
||||||
|
ReverseIterator rend() { return Iterator{nullptr, min}; }
|
||||||
|
|
||||||
|
// misc that can be implemented with the above or trivially
|
||||||
|
void clear() {
|
||||||
|
this->root = std::move(std::nullopt);
|
||||||
|
this->_size = 0;
|
||||||
|
}
|
||||||
|
Mapped_T &at(const Key_T &key) {
|
||||||
|
auto ret = this->find(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).first;
|
||||||
|
}
|
||||||
|
Mapped_T &operator[](const Key_T &key) {
|
||||||
|
this->insert({key, {}});
|
||||||
|
return this->at(key);
|
||||||
|
}
|
||||||
|
template <typename IT_T> void insert(IT_T range_beg, IT_T range_end) {
|
||||||
|
while (range_beg != range_end) {
|
||||||
|
auto [first, second] = *range_beg;
|
||||||
|
this->insert(std::make_pair(first, second));
|
||||||
|
++range_beg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void erase(const Key_T &key) { this->erase(this->find(key)); }
|
||||||
|
// TODO:
|
||||||
|
friend bool operator==(const Map &lhs, const Map &rhs) { assert(false); }
|
||||||
|
friend bool operator!=(const Map &lhs, const Map &rhs) { assert(false); }
|
||||||
|
friend bool operator<(const Map &lhs, const Map &rhs) { assert(false); }
|
||||||
};
|
};
|
||||||
} // namespace cs440
|
} // namespace cs440
|
||||||
#endif
|
#endif
|
||||||
|
|
30
t.cpp
30
t.cpp
|
@ -1,22 +1,20 @@
|
||||||
#include "Map.hpp"
|
#include "Map.hpp"
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
template class cs440::Map<int, int>;
|
template class cs440::Map<int, int>;
|
||||||
int main(void) {
|
int main(void) {
|
||||||
cs440::Map<int, int> a;
|
// cs440::Map<int, int> a;
|
||||||
for (std::size_t i = 1; i <= 10; i++) {
|
// for (std::size_t i = 10; i >= 1; i--) {
|
||||||
a.insert({i, i});
|
// a.insert({i, i});
|
||||||
a.check();
|
// for (std::size_t j = 10; j >= i; j--) {
|
||||||
for (std::size_t j = 1; j <= i; j++) {
|
// }
|
||||||
a.find(j).check();
|
// }
|
||||||
}
|
// for (std::size_t i = 10; i >= 5; i--) {
|
||||||
}
|
// std::cout << i << std::endl;
|
||||||
for (std::size_t i = 1; i <= 10; i++) {
|
// auto b = a.find(i);
|
||||||
a.find(i).check();
|
// a.erase(b);
|
||||||
}
|
// for (std::size_t j = 1; j <= i; j++) {
|
||||||
for (std::size_t i = 1; i <= 5; i++) {
|
// }
|
||||||
std::cout << i << std::endl;
|
// }
|
||||||
auto b = a.find(i);
|
|
||||||
a.erase(b);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue