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:
parent
be847faa8c
commit
894021ab61
1 changed files with 27 additions and 47 deletions
74
Map.hpp
74
Map.hpp
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue