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 <stdexcept>
#include <utility> #include <utility>
#include <vector> #include <vector>
// everything is super interconnected so some forward declarations are needed at
// various points
namespace cs440 { namespace cs440 {
template <typename Key_T, typename Mapped_T> class Map; template <typename Key_T, typename Mapped_T> class Map;
@ -16,13 +19,15 @@ template <typename Key_T, typename Mapped_T> class Map;
namespace { namespace {
enum class Color { Red, Black }; enum class Color { Red, Black };
template <typename Key_T, typename Mapped_T> struct BookKeeping { 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>; using ValueType = std::pair<const Key_T, Mapped_T>;
Map<Key_T, Mapped_T> &parent; Map<Key_T, Mapped_T> &parent;
ValueType value; ValueType value;
std::size_t self; std::size_t self;
std::size_t next;
std::size_t prev;
Color color; Color color;
std::optional<std::size_t> next;
std::optional<std::size_t> prev;
}; };
} // namespace } // namespace
// https://en.wikipedia.org/wiki/Red%E2%80%93black_tree // https://en.wikipedia.org/wiki/Red%E2%80%93black_tree
@ -43,17 +48,27 @@ public:
friend class Iterator; friend class Iterator;
friend class ConstIterator; friend class ConstIterator;
friend class ReverseIterator; friend class ReverseIterator;
friend struct BookKeeping<Key_T, Mapped_T>;
// TODO: Iterator functionality // TODO: Iterator functionality
class Iterator { class Iterator {
friend class Map<Key_T, Mapped_T>;
friend struct BookKeeping<Key_T, Mapped_T>;
public: public:
private: private:
BookKeeping<Key_T, Mapped_T> &parent; enum class PastElem { start, end, neither };
// TODO: replace queues with functions that just go through the entire in // pointer needed so we can replace as needed
// order traversal and give the next/previous element 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: public:
Iterator() = delete; Iterator() = delete;
Iterator(std::optional<BookKeeping<Key_T, Mapped_T>> &parent)
: parent{parent} {}
ConstIterator to_const() const { return ConstIterator(*this); } ConstIterator to_const() const { return ConstIterator(*this); }
Iterator &operator++() { return *this; } Iterator &operator++() { return *this; }
Iterator operator++(int) { Iterator operator++(int) {
@ -90,14 +105,16 @@ public:
}; };
class ConstIterator { class ConstIterator {
public: public:
friend class Map<Key_T, Mapped_T>;
friend class Iterator;
using underlying = Iterator; using underlying = Iterator;
private: private:
underlying store_iter; underlying store_iter;
ConstIterator(underlying iter) : store_iter{iter} {}
public: public:
ConstIterator() = delete; ConstIterator() = delete;
ConstIterator(underlying iter) : store_iter{iter} {}
friend bool operator==(ConstIterator const &lhs, ConstIterator const &rhs) { friend bool operator==(ConstIterator const &lhs, ConstIterator const &rhs) {
return lhs.store_iter == rhs.store_iter; return lhs.store_iter == rhs.store_iter;
} }
@ -130,6 +147,7 @@ public:
}; };
class ReverseIterator { class ReverseIterator {
public: public:
friend class Map<Key_T, Mapped_T>;
using underlying = typename std::vector<std::optional<ValueType>>::iterator; using underlying = typename std::vector<std::optional<ValueType>>::iterator;
private: private:
@ -169,32 +187,17 @@ public:
return count; return count;
} }
bool empty() const { return this->store.empty(); } bool empty() const { return this->store.empty(); }
Iterator begin() { // TODO: Iterator creation
std::size_t start = 0; Iterator begin() {}
while (2 * (start - store.begin()) + 1 < store.size()) { Iterator end() {}
store = 2 * store + 2; ConstIterator begin() const {}
} ConstIterator end() const {}
return Iterator(store.cbegin() + start); ConstIterator cbegin() const {}
} ConstIterator cend() const {}
Iterator end() { return Iterator(store.end()); } ReverseIterator rbegin() {}
ConstIterator begin() const { ReverseIterator rend() {}
std::size_t start = 0; // TODO: actually return an iterator from find and deal with error cases
while (2 * (start - store.begin()) + 1 < store.size()) { // correctly, also need to update for new bookkeeping type
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()); }
Iterator find(const Key_T &key) { Iterator find(const Key_T &key) {
std::size_t idx = 0; std::size_t idx = 0;
while (store[idx].first != key) { while (store[idx].first != key) {
@ -241,9 +244,69 @@ public:
const Mapped_T &at(const Key_T &key) const { return this->at(key); } const Mapped_T &at(const Key_T &key) const { return this->at(key); }
Mapped_T &operator[](const Key_T &key) { 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 // TODO: single insert
// OH NO IT SHOULD BE RED-BLACK // 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) { template <typename IT_T> void insert(IT_T range_beg, IT_T range_end) {
std::for_each(range_beg, range_end, std::for_each(range_beg, range_end,
[&](ValueType &val) { this->insert(val); }); [&](ValueType &val) { this->insert(val); });