From c47ee41caf3dd8c0821d4e1a7f97755803b45d4d Mon Sep 17 00:00:00 2001 From: Pagwin Date: Wed, 20 Nov 2024 18:15:34 -0500 Subject: [PATCH] slowly realizing that the array based binary tree is impractical --- Map.hpp | 133 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 98 insertions(+), 35 deletions(-) diff --git a/Map.hpp b/Map.hpp index a23cd52..f5748fa 100644 --- a/Map.hpp +++ b/Map.hpp @@ -9,6 +9,9 @@ #include #include #include + +// everything is super interconnected so some forward declarations are needed at +// various points namespace cs440 { template class Map; @@ -16,13 +19,15 @@ template class Map; namespace { enum class Color { Red, Black }; template struct BookKeeping { + friend class Map; using ValueType = std::pair; Map &parent; ValueType value; std::size_t self; - std::size_t next; - std::size_t prev; Color color; + + std::optional next; + std::optional 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; // TODO: Iterator functionality class Iterator { + friend class Map; + friend struct BookKeeping; + public: private: - BookKeeping &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 *parent; + + // TODO: next/prev found in bookkeeping + // Note: only used when past first/last element + PastElem use; + std::optional next_or_prev; + Iterator(std::optional> &parent) + : parent{&parent}, use{PastElem::neither}, next_or_prev{std::nullopt} {} + public: Iterator() = delete; - Iterator(std::optional> &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; + 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; using underlying = typename std::vector>::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 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 &parent = this->store.at(parent_idx).value(); + } + +public: // TODO: single insert // OH NO IT SHOULD BE RED-BLACK - std ::pair insert(const ValueType &) {} + std::pair insert(const ValueType &val) { + + BookKeeping 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 void insert(IT_T range_beg, IT_T range_end) { std::for_each(range_beg, range_end, [&](ValueType &val) { this->insert(val); });