slowly realizing that the array based binary tree is impractical
This commit is contained in:
parent
894021ab61
commit
c47ee41caf
1 changed files with 98 additions and 35 deletions
133
Map.hpp
133
Map.hpp
|
@ -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); });
|
||||||
|
|
Loading…
Reference in a new issue