Redid iterator bookkeeping

Everything works via a bookkeeping type which tracks a bunch of stuff
like the color and neighbors. This is needed to make the iterator go
brrrr instead of needing to relocate the relevant tree node every time
we want to increment the iterator.
This commit is contained in:
Pagwin 2024-11-19 22:36:09 -05:00
parent be847faa8c
commit 894021ab61
No known key found for this signature in database
GPG key ID: 81137023740CA260

74
Map.hpp
View file

@ -11,8 +11,20 @@
#include <vector> #include <vector>
namespace cs440 { namespace cs440 {
enum class Color { Red, Black }; template <typename Key_T, typename Mapped_T> class Map;
namespace {
enum class Color { Red, Black };
template <typename Key_T, typename Mapped_T> struct BookKeeping {
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;
};
} // namespace
// https://en.wikipedia.org/wiki/Red%E2%80%93black_tree // https://en.wikipedia.org/wiki/Red%E2%80%93black_tree
template <typename Key_T, typename Mapped_T> class Map { template <typename Key_T, typename Mapped_T> class Map {
private: private:
@ -20,74 +32,42 @@ private:
// idx 0 = root // idx 0 = root
// left = parent * 2 + 1 // left = parent * 2 + 1
// right = parent * 2 + 2 // right = parent * 2 + 2
std::vector<std::optional<ValueType>> store; std::vector<std::optional<BookKeeping<Key_T, Mapped_T>>> store;
std::vector<Color> coloration; std::vector<Color> coloration;
public: public:
class Iterator; class Iterator;
class ConstIterator; class ConstIterator;
class ReverseIterator; class ReverseIterator;
friend class Iterator;
friend class ConstIterator;
friend class ReverseIterator;
// TODO: Iterator functionality // TODO: Iterator functionality
class Iterator { class Iterator {
public: public:
private: private:
// in order traversal, deque used as the stack we traverse up after each BookKeeping<Key_T, Mapped_T> &parent;
// right hand side traversal completes // TODO: replace queues with functions that just go through the entire in
// // order traversal and give the next/previous element
// if a right child exists traverse down to the left most child of that
// child pushing to stack elements that are passed if it doesn't pop from
// the stack
//
std::vector<ValueType> &parent;
std::deque<std::size_t> forward_traversal;
std::deque<std::size_t> backward_traversal;
std::size_t current;
public: public:
Iterator() = delete; Iterator() = delete;
Iterator(std::vector<ValueType> &parent, std::size_t current) Iterator(std::optional<BookKeeping<Key_T, Mapped_T>> &parent)
: parent{parent}, forward_traversal{}, backward_traversal{}, : parent{parent} {}
current{current} {} ConstIterator to_const() const { return ConstIterator(*this); }
ConstIterator to_const() const { return ConstIterator(this); } Iterator &operator++() { return *this; }
Iterator &operator++() {
backward_traversal.push_back(current);
std::size_t next = current * 2 + 2;
while (next < parent.size() && parent.at(next).has_value()) {
forward_traversal.push_back(next);
next = next * 2 + 1;
}
current = forward_traversal.back();
forward_traversal.pop_back();
if (this->forward_traversal.empty()) {
// deref can just check for nullopt to see if it's end
current = next;
} else {
// pop from stack
current = forward_traversal.back();
forward_traversal.pop_back();
}
return *this;
}
Iterator operator++(int) { Iterator operator++(int) {
Iterator tmp = *this; Iterator tmp = *this;
++(*this); ++(*this);
return tmp; return tmp;
} }
Iterator &operator--() { Iterator &operator--() { return *this; }
std::size_t tmp = backward_traversal.back();
backward_traversal.pop_back();
if (tmp > current) {
forward_traversal.push_back(current);
}
current = tmp;
return *this;
}
Iterator operator--(int) { Iterator operator--(int) {
Iterator tmp = *this; Iterator tmp = *this;
--(*this); --(*this);
return tmp; return tmp;
} }
ValueType &operator*() const { return parent.at(current); } ValueType &operator*() const { return parent.parent.at(parent.self); }
ValueType *operator->() const { return &**this; } ValueType *operator->() const { return &**this; }
friend bool operator==(Iterator const &lhs, Iterator const &rhs) { friend bool operator==(Iterator const &lhs, Iterator const &rhs) {
return lhs.store_iter == rhs.store_iter; return lhs.store_iter == rhs.store_iter;