slowly realizing that the array based binary tree is impractical
This commit is contained in:
parent
894021ab61
commit
c47ee41caf
1 changed files with 98 additions and 35 deletions
133
Map.hpp
133
Map.hpp
|
@ -9,6 +9,9 @@
|
|||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// everything is super interconnected so some forward declarations are needed at
|
||||
// various points
|
||||
namespace cs440 {
|
||||
|
||||
template <typename Key_T, typename Mapped_T> class Map;
|
||||
|
@ -16,13 +19,15 @@ template <typename Key_T, typename Mapped_T> class Map;
|
|||
namespace {
|
||||
enum class Color { Red, Black };
|
||||
template <typename Key_T, typename Mapped_T> struct BookKeeping {
|
||||
friend class Map<Key_T, Mapped_T>;
|
||||
using ValueType = std::pair<const Key_T, Mapped_T>;
|
||||
Map<Key_T, Mapped_T> &parent;
|
||||
ValueType value;
|
||||
std::size_t self;
|
||||
std::size_t next;
|
||||
std::size_t prev;
|
||||
Color color;
|
||||
|
||||
std::optional<std::size_t> next;
|
||||
std::optional<std::size_t> prev;
|
||||
};
|
||||
} // namespace
|
||||
// https://en.wikipedia.org/wiki/Red%E2%80%93black_tree
|
||||
|
@ -43,17 +48,27 @@ public:
|
|||
friend class Iterator;
|
||||
friend class ConstIterator;
|
||||
friend class ReverseIterator;
|
||||
friend struct BookKeeping<Key_T, Mapped_T>;
|
||||
// TODO: Iterator functionality
|
||||
class Iterator {
|
||||
friend class Map<Key_T, Mapped_T>;
|
||||
friend struct BookKeeping<Key_T, Mapped_T>;
|
||||
|
||||
public:
|
||||
private:
|
||||
BookKeeping<Key_T, Mapped_T> &parent;
|
||||
// TODO: replace queues with functions that just go through the entire in
|
||||
// order traversal and give the next/previous element
|
||||
enum class PastElem { start, end, neither };
|
||||
// pointer needed so we can replace as needed
|
||||
BookKeeping<Key_T, Mapped_T> *parent;
|
||||
|
||||
// TODO: next/prev found in bookkeeping
|
||||
// Note: only used when past first/last element
|
||||
PastElem use;
|
||||
std::optional<std::size_t> next_or_prev;
|
||||
Iterator(std::optional<BookKeeping<Key_T, Mapped_T>> &parent)
|
||||
: parent{&parent}, use{PastElem::neither}, next_or_prev{std::nullopt} {}
|
||||
|
||||
public:
|
||||
Iterator() = delete;
|
||||
Iterator(std::optional<BookKeeping<Key_T, Mapped_T>> &parent)
|
||||
: parent{parent} {}
|
||||
ConstIterator to_const() const { return ConstIterator(*this); }
|
||||
Iterator &operator++() { return *this; }
|
||||
Iterator operator++(int) {
|
||||
|
@ -90,14 +105,16 @@ public:
|
|||
};
|
||||
class ConstIterator {
|
||||
public:
|
||||
friend class Map<Key_T, Mapped_T>;
|
||||
friend class Iterator;
|
||||
using underlying = Iterator;
|
||||
|
||||
private:
|
||||
underlying store_iter;
|
||||
ConstIterator(underlying iter) : store_iter{iter} {}
|
||||
|
||||
public:
|
||||
ConstIterator() = delete;
|
||||
ConstIterator(underlying iter) : store_iter{iter} {}
|
||||
friend bool operator==(ConstIterator const &lhs, ConstIterator const &rhs) {
|
||||
return lhs.store_iter == rhs.store_iter;
|
||||
}
|
||||
|
@ -130,6 +147,7 @@ public:
|
|||
};
|
||||
class ReverseIterator {
|
||||
public:
|
||||
friend class Map<Key_T, Mapped_T>;
|
||||
using underlying = typename std::vector<std::optional<ValueType>>::iterator;
|
||||
|
||||
private:
|
||||
|
@ -169,32 +187,17 @@ public:
|
|||
return count;
|
||||
}
|
||||
bool empty() const { return this->store.empty(); }
|
||||
Iterator begin() {
|
||||
std::size_t start = 0;
|
||||
while (2 * (start - store.begin()) + 1 < store.size()) {
|
||||
store = 2 * store + 2;
|
||||
}
|
||||
return Iterator(store.cbegin() + start);
|
||||
}
|
||||
Iterator end() { return Iterator(store.end()); }
|
||||
ConstIterator begin() const {
|
||||
std::size_t start = 0;
|
||||
while (2 * (start - store.begin()) + 1 < store.size()) {
|
||||
store = 2 * store + 2;
|
||||
}
|
||||
return ConstIterator(store.cbegin() + start);
|
||||
}
|
||||
ConstIterator end() const { return ConstIterator(store.cend()); }
|
||||
ConstIterator cbegin() const { return this->begin(); }
|
||||
ConstIterator cend() const { return this->end(); }
|
||||
ReverseIterator rbegin() {
|
||||
std::size_t start = 0;
|
||||
while (2 * (start - store.begin()) + 1 < store.size()) {
|
||||
store = 2 * store + 2;
|
||||
}
|
||||
return ReverseIterator(store.begin() + start);
|
||||
}
|
||||
ReverseIterator rend() { return ReverseIterator(store.end()); }
|
||||
// TODO: Iterator creation
|
||||
Iterator begin() {}
|
||||
Iterator end() {}
|
||||
ConstIterator begin() const {}
|
||||
ConstIterator end() const {}
|
||||
ConstIterator cbegin() const {}
|
||||
ConstIterator cend() const {}
|
||||
ReverseIterator rbegin() {}
|
||||
ReverseIterator rend() {}
|
||||
// TODO: actually return an iterator from find and deal with error cases
|
||||
// correctly, also need to update for new bookkeeping type
|
||||
Iterator find(const Key_T &key) {
|
||||
std::size_t idx = 0;
|
||||
while (store[idx].first != key) {
|
||||
|
@ -241,9 +244,69 @@ public:
|
|||
const Mapped_T &at(const Key_T &key) const { return this->at(key); }
|
||||
Mapped_T &operator[](const Key_T &key) { return this->at(key); }
|
||||
|
||||
private:
|
||||
Color getColor(std::size_t i) {
|
||||
if (this->store.size() <= i) {
|
||||
return Color::Black;
|
||||
}
|
||||
if (!this->store.at(i).has_value()) {
|
||||
return Color::Black;
|
||||
}
|
||||
return this->store.at(i).value().color;
|
||||
}
|
||||
std::size_t find_null(const Key_T &key) {
|
||||
std::size_t idx = 0;
|
||||
while (store[idx].first != key) {
|
||||
if (idx >= store.size()) {
|
||||
return this->end();
|
||||
}
|
||||
if (store[idx].first < key) {
|
||||
if (idx * 2 + 1 > store.size() || !store.at(idx * 2 + 1).has_value()) {
|
||||
idx = idx * 2 + 1;
|
||||
break;
|
||||
}
|
||||
idx = idx * 2 + 1;
|
||||
} else {
|
||||
if (idx * 2 + 2 > store.size() || !store.at(idx * 2 + 2).has_value()) {
|
||||
idx = idx * 2 + 2;
|
||||
break;
|
||||
}
|
||||
idx = idx * 2 + 2;
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
enum class Direction { left, right };
|
||||
void insert_helper(std::size_t idx, BookKeeping<Key_T, Mapped_T> to_insert) {
|
||||
// might as well make sure
|
||||
to_insert.color = Color::Red;
|
||||
std::size_t parent_idx;
|
||||
Direction relation;
|
||||
if (idx % 2 == 1) {
|
||||
parent_idx = (idx - 1) / 2;
|
||||
relation = Direction::left;
|
||||
} else {
|
||||
parent_idx = (idx - 1) / 2;
|
||||
relation = Direction::right;
|
||||
}
|
||||
BookKeeping<Key_T, Mapped_T> &parent = this->store.at(parent_idx).value();
|
||||
}
|
||||
|
||||
public:
|
||||
// TODO: single insert
|
||||
// OH NO IT SHOULD BE RED-BLACK
|
||||
std ::pair<Iterator, bool> insert(const ValueType &) {}
|
||||
std::pair<Iterator, bool> insert(const ValueType &val) {
|
||||
|
||||
BookKeeping<Key_T, Mapped_T> new_node;
|
||||
new_node.color = Color::Red;
|
||||
new_node.value = val;
|
||||
new_node.parent = *this;
|
||||
|
||||
if (this->store.size() == 0) {
|
||||
new_node.self = 0;
|
||||
this->store.push_back(new_node);
|
||||
}
|
||||
}
|
||||
template <typename IT_T> void insert(IT_T range_beg, IT_T range_end) {
|
||||
std::for_each(range_beg, range_end,
|
||||
[&](ValueType &val) { this->insert(val); });
|
||||
|
|
Loading…
Reference in a new issue