// commenting everything out when I commit so all commits my code technically // compiles #include #include #include #include #include #include #include #include #include namespace cs440 { template class Map; namespace { enum class Color { Red, Black }; template struct BookKeeping { using ValueType = std::pair; Map &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 template class Map { private: using ValueType = std::pair; // idx 0 = root // left = parent * 2 + 1 // right = parent * 2 + 2 std::vector>> store; std::vector coloration; public: class Iterator; class ConstIterator; class ReverseIterator; friend class Iterator; friend class ConstIterator; friend class ReverseIterator; // TODO: Iterator functionality class Iterator { public: private: BookKeeping &parent; // TODO: replace queues with functions that just go through the entire in // order traversal and give the next/previous element public: Iterator() = delete; Iterator(std::optional> &parent) : parent{parent} {} ConstIterator to_const() const { return ConstIterator(*this); } Iterator &operator++() { return *this; } Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; } Iterator &operator--() { return *this; } Iterator operator--(int) { Iterator tmp = *this; --(*this); return tmp; } ValueType &operator*() const { return parent.parent.at(parent.self); } ValueType *operator->() const { return &**this; } friend bool operator==(Iterator const &lhs, Iterator const &rhs) { return lhs.store_iter == rhs.store_iter; } friend bool operator!=(Iterator const &lhs, Iterator const &rhs) { return lhs.store_iter != rhs.store_iter; } friend bool operator==(ConstIterator const &lhs, Iterator const &rhs) { return lhs == rhs.to_const(); } friend bool operator!=(ConstIterator const &lhs, Iterator const &rhs) { return lhs != rhs.to_const(); } friend bool operator==(Iterator const &lhs, ConstIterator const &rhs) { return lhs.to_const() == rhs; } friend bool operator!=(Iterator const &lhs, ConstIterator const &rhs) { return lhs.to_const() != rhs; } }; class ConstIterator { public: using underlying = Iterator; private: underlying store_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; } ConstIterator &operator++() { ++this->store_iter; return *this; } ConstIterator operator++(int) { ConstIterator tmp = *this; this->store_iter++; return tmp; } ConstIterator &operator--() { --this->store_iter; return *this; } ConstIterator operator--(int) { ConstIterator tmp = *this; this->store_iter--; return tmp; } const ValueType &operator*() const { return *this->store_iter; } const ValueType *operator->() const { // I find this rather funny return this->store_iter.operator->(); } friend bool operator!=(ConstIterator const &lhs, ConstIterator const &rhs) { return lhs.store_iter != rhs.store_iter; } }; class ReverseIterator { public: using underlying = typename std::vector>::iterator; private: underlying store_iter; public: ReverseIterator() = delete; ReverseIterator(underlying store_iter) : store_iter{store_iter} {} ReverseIterator &operator++() {} ReverseIterator operator++(int) {} ReverseIterator &operator--() {} ReverseIterator operator--(int) {} ValueType &operator*() const {} ValueType *operator->() const {} friend bool operator==(ReverseIterator const &lhs, ReverseIterator const &rhs) { return lhs.store_iter == rhs.store_iter; } friend bool operator!=(ConstIterator const &lhs, ConstIterator const &rhs) { return lhs.store_iter != rhs.store_iter; } }; Map() : store{} {} Map(const Map &rhs) : store{rhs.store} {} Map &operator=(const Map &rhs) { this->store = rhs.store; } Map(std::initializer_list elems) : store{} { this->insert(elems.begin(), elems.end()); } // who cares we're using vector ~Map() {} size_t size() const { std::size_t count = 0; for (auto &m_pair : this->store) { count += m_pair.has_value() ? 1 : 0; } 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()); } Iterator find(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) { idx = idx * 2 + 1; } else { idx = idx * 2 + 2; } } } ConstIterator find(const Key_T &key) const { std::size_t idx = 0; while (store[idx].first != key) { if (idx >= store.size()) { return this->end(); } if (store[idx].first < key) { idx = idx * 2 + 1; } else { idx = idx * 2 + 2; } } } Mapped_T &at(const Key_T &key) { std::size_t i = 0; while (this->store.at(i).has_value()) { switch (true) { case this->store.at(i).first == key: return this->store.at(i).second; case this->store.at(i).first < key: i = 2 * i + 1; break; case this->store.at(i).first > key: i = 2 * i + 2; break; } } throw std::out_of_range{""}; } const Mapped_T &at(const Key_T &key) const { return this->at(key); } Mapped_T &operator[](const Key_T &key) { return this->at(key); } // TODO: single insert // OH NO IT SHOULD BE RED-BLACK std ::pair insert(const ValueType &) {} template void insert(IT_T range_beg, IT_T range_end) { std::for_each(range_beg, range_end, [&](ValueType &val) { this->insert(val); }); } // TODO: erase via iterator void erase(Iterator pos) { // RED BLACK TREE oh no } void erase(const Key_T &key) { this->erase(this->find(key)); } void clear() { this->store = {}; } friend bool operator==(const Map &lhs, const Map &rhs) { if (lhs.store.size() != rhs.store.size()) { return false; } auto liter = lhs.cbegin(); auto riter = rhs.cbegin(); // both must be the same length so this is fine while (liter != lhs.cend()) { if (*liter != *riter) { return false; } liter++; riter++; } return true; } friend bool operator!=(const Map &lhs, const Map &rhs) { return !(lhs == rhs); } friend bool operator<(const Map &lhs, const Map &rhs) { std::size_t lhs_i = 0; std::size_t rhs_i = 0; for (; lhs_i < lhs.store.size() && rhs_i < rhs.store.size(); lhs_i++, rhs_i++) { bool lhs_exhaust = false; while (!lhs.store[lhs_i].has_value()) { lhs_i++; if (lhs.store.size() >= lhs_i) { lhs_exhaust = true; break; } } bool rhs_exhaust = false; while (!rhs.store[rhs_i].has_value()) { rhs_i++; if (rhs.store.size() >= rhs_i) { rhs_exhaust = true; break; } } if (lhs_exhaust && !rhs_exhaust) { return true; } if (lhs_exhaust || rhs_exhaust) { break; } if (lhs.store[lhs_i] != rhs.store[rhs_i]) { return lhs.store[lhs_i] < rhs.store[rhs_i]; } } return false; } }; } // namespace cs440