slowly realizing that the array based binary tree is impractical

This commit is contained in:
Pagwin 2024-11-20 18:15:34 -05:00
parent 894021ab61
commit c47ee41caf
No known key found for this signature in database
GPG key ID: 81137023740CA260

133
Map.hpp
View file

@ -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); });