#include #include #include #include #include #include #include #include using std::prev; template> class List { private: class Node; template class base_iterator; public: using iterator = base_iterator; using const_iterator = base_iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; explicit List(const Allocator& alloc = Allocator()) : allocator_node_(alloc) { AllocateEnd(); } List(size_t count, const T& value, const Allocator& alloc = Allocator()) : allocator_node_(alloc) { AllocateEnd(); for (size_t i = 0; i < count; ++i) { Node* tmp = allocator_node_.allocate(1); alloc_traits_::construct(allocator_node_, tmp, value); Link(end_->l, tmp); } size_ = count; } List(size_t count, const Allocator& alloc = Allocator()) : allocator_node_(alloc) { AllocateEnd(); for (size_t i = 0; i < count; ++i) { Node* tmp = allocator_node_.allocate(1); alloc_traits_::construct(allocator_node_, tmp); Link(end_->l, tmp); } size_ = count; } List(const List& another) { allocator_node_ = alloc_traits_::select_on_container_copy_construction(another.allocator_node_); AllocateEnd(); for (const T& i: another) { Node* tmp = allocator_node_.allocate(1); alloc_traits_::construct(allocator_node_, tmp, i); Link(end_->l, tmp); } size_ = another.size(); } List(List&& another) : end_(std::move(another.end_)), size_(std::move(another.size_)) { another.end_ = nullptr; } List& operator=(const List& another) { if (this == &another) return *this; if (alloc_traits_::propagate_on_container_copy_assignment::value && allocator_node_ != another.allocator_node_) { allocator_node_ = another.allocator_node_; } auto it1 = begin(); auto it2 = another.begin(); for (size_t i = 0; i < std::min(another.size(), size()); ++i) { *it1 = *it2; ++it1; ++it2; } if (another.size() > size()) { while (size() != another.size()) { push_back(*it2); ++it2; } } else { while (size() != another.size()) { pop_back(); } } return *this; } List& operator=(List&& another) { auto tmp(std::move(another)); std::swap(end_, tmp.end_); std::swap(size_, tmp.size_); return *this; } ~List() { if (end_) { while (end_ != end_->r) { erase(iterator(end_->r)); } allocator_node_.deallocate(end_, 1); // TODO } } Allocator get_allocator() { return allocator_node_; } void push_back(const T& value) { insert(end(), value); } void push_back(T&& value) { insert(end(), std::move(value)); } void push_front(const T& value) { insert(begin(), value); } void pop_back() { erase(std::prev(end())); } void pop_front() { erase(begin()); } template iterator emplace_back(Args&&... args) { Node* tmp = allocator_node_.allocate(1); tmp->l = nullptr; tmp->r = nullptr; Allocator tmp1 = allocator_node_; std::allocator_traits::construct(tmp1, &tmp->value, std::forward(args)...); Link(std::prev(end()).it, tmp); ++size_; return iterator(tmp); } size_t size() const { return size_; } iterator begin() { return iterator(end_->r); } iterator end() { return iterator(end_); } const_iterator begin() const { return const_iterator(end_->r); } const_iterator end() const { return const_iterator(end_); } const_iterator cbegin() const { return const_iterator(end_->r); } const_iterator cend() const { return const_iterator(end_); } reverse_iterator rbegin() { return reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(cend()); } const_reverse_iterator rend() const { return const_reverse_iterator(cbegin()); } const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); } const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); } iterator insert(const_iterator it, const T& value) { Node* tmp = allocator_node_.allocate(1); tmp->l = nullptr; tmp->r = nullptr; std::allocator_traits::construct(allocator_node_, tmp, value); Link(const_cast(std::prev(it).it), tmp); ++size_; return iterator(tmp); } iterator insert(const_iterator it, T&& value) { Node* tmp = allocator_node_.allocate(1); tmp->l = nullptr; tmp->r = nullptr; alloc_traits_::construct(allocator_node_, tmp, std::move(value)); Link(const_cast(std::prev(it).it), tmp); ++size_; return iterator(tmp); } void erase(const_iterator it) { Node* tmp = const_cast(it.it); tmp->l->r = tmp->r; tmp->r->l = tmp->l; std::allocator_traits::destroy(allocator_node_, tmp); allocator_node_.deallocate(tmp, 1); --size_; } void relink(iterator a, iterator b) { Link(a.it, b.it); } private: void AllocateEnd() { end_ = allocator_node_.allocate(1); end_->l = end_; end_->r = end_; } void Link(Node* l, Node* x) { Node* r = l->r; if (r == x) return; auto xl = x->l, xr = x->r; if (xl) xl->r = xr; if (xr) xr->l = xl; x->l = l; x->r = r; l->r = x; r->l = x; } template class base_iterator { friend List; std::conditional_t it; using U = std::conditional_t; public: using iterator_category = std::bidirectional_iterator_tag; using value_type = U; using pointer = U*; using reference = U&; using difference_type = int; base_iterator() : it(nullptr) {} base_iterator(Node* v) { it = v; } base_iterator(const base_iterator&) = default; operator base_iterator() { return base_iterator(it); } U& operator*() const { return it->value; } U* operator->() const { return &it->value; } base_iterator& operator++()& { it = it->r; return *this; } base_iterator operator++(int)& { base_iterator tmp = *this; it = it->r; return tmp; } base_iterator& operator--()& { it = it->l; return *this; } base_iterator operator--(int)& { base_iterator tmp = *this; it = it->l; return tmp; } friend bool operator==(base_iterator first, base_iterator second) { return first.it == second.it; } friend bool operator!=(base_iterator first, base_iterator second) { return first.it != second.it; } base_iterator& operator=(const base_iterator& another) { it = another.it; return *this; } }; struct Node { Node* l = nullptr; Node* r = nullptr; T value; Node() = default; Node(const T& value) : value(value) {} Node(T&& value) : value(std::move(value)) {} Node& operator=(const Node& another) { value = another.value; } }; typename std::allocator_traits::template rebind_alloc allocator_node_; using alloc_traits_ = std::allocator_traits; Node* end_ = nullptr; size_t size_ = 0; }; template, typename Equal = std::equal_to, typename Alloc = std::allocator>> class UnorderedMap { private: using NonConstNodeType = std::pair; using ListNonConstNodeType = List::template rebind_alloc>>; struct Node { std::pair pair; size_t hash; Node() {} Node(const Node& another) : pair(another.pair), hash(another.hash) {} Node(Node&& another) : pair(std::move(another.pair)), hash(another.hash) { another.hash = 0; } Node(Key&& key, Value&& value, const Hash& hash_) : pair(std::make_pair(std::move(key), std::move(value))) { hash = hash_(key); } Node(const Key& key, const Value& value, const Hash& hash_) : pair(std::make_pair(key, value)){ hash = hash_(key); } Node(std::pair&& pair_, const Hash& hash_) : pair(std::move(pair_)) { hash = hash_(pair.first); } Node(const std::pair& pair_, const Hash& hash_) : pair(pair_) { hash = hash_(pair.first); } }; using NewList = List::template rebind_alloc>; NewList new_all_pairs; std::vector new_hash_table; size_t GetBucketIdx(const Key& key) { return hash_(key) % new_hash_table.size(); } size_t GetBucketIdx(const Node& node) { return node.hash % new_hash_table.size(); } public: using new_iterator = typename NewList::iterator; template struct base_iterator { using value_type = std::conditional_t, std::pair>; using iterator_category = std::bidirectional_iterator_tag; using pointer = value_type*; using reference = value_type&; using difference_type = int; new_iterator it; base_iterator() {} base_iterator(const base_iterator&) = default; base_iterator(const new_iterator& another) : it(another) {} operator base_iterator() { return base_iterator(it); } base_iterator& operator=(const base_iterator&) = default; reference operator*() { return *reinterpret_cast*>(&it->pair); } pointer operator->() { return reinterpret_cast*>(&it->pair); } base_iterator& operator++()& { ++it; return *this; } base_iterator operator++(int)& { base_iterator tmp(*this); ++it; return tmp; } base_iterator& operator--()& { --it; return *this; } base_iterator operator--(int)& { base_iterator tmp(*this); --it; return tmp; } bool operator==(const base_iterator& another) { return it == another.it; } bool operator!=(const base_iterator& another) { return it != another.it; } }; using iterator = base_iterator; using const_iterator = base_iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using NodeType = std::pair; UnorderedMap() { new_hash_table.resize(1000, new_all_pairs.end()); } UnorderedMap(const UnorderedMap& another) : new_all_pairs(another.new_all_pairs), hash_(another.hash_), equal_(another.equal_) { new_hash_table.resize(another.new_hash_table.size(), new_all_pairs.end()); new_hash_table[GetBucketIdx(*new_all_pairs.begin())] = new_all_pairs.begin(); for (auto it = std::next(new_all_pairs.begin()); it != new_all_pairs.end(); ++it) { if (GetBucketIdx(*it) != GetBucketIdx(*prev(it))) new_hash_table[GetBucketIdx(*it)] = it; } } UnorderedMap(UnorderedMap&&) = default; UnorderedMap& operator=(const UnorderedMap& another) { this->all_pairs = another.all_pairs; this->hash_table_ = another.hash_table_; this->hash_ = another.hash_; this->equal_ = another.equal_; this->max_load_factor_ = another.max_load_factor_; return *this; } UnorderedMap& operator=(UnorderedMap&&) = default; size_t size() const { return new_all_pairs.size(); } Value& at(const Key& key) { auto it = find(key); if (it == end()) { throw std::out_of_range("uhaha"); } else { return it->second; } } Value& operator[](const Key& key) { return insert(std::make_pair(key, Value())).first->second; } template std::pair emplace(Args&&... args) { if (new_hash_table.size() < new_all_pairs.size()) rehash(new_hash_table.size() * 1.8); new_all_pairs.emplace_back(std::forward(args)..., hash_); auto& node = *std::prev(new_all_pairs.end()); auto& key = node.pair.first; size_t hash = GetBucketIdx(node); if (new_hash_table[hash] != new_all_pairs.end()) { auto i = new_hash_table[hash]; while (i != prev(new_all_pairs.end()) && GetBucketIdx(*i) == hash) { if (equal_(i->pair.first, key)) break; ++i; } if (i != std::prev(new_all_pairs.end()) && equal_(i->pair.first, key)) { new_all_pairs.pop_back(); return {i, false}; } else { auto it = std::prev(new_all_pairs.end()); new_all_pairs.relink(std::prev(i), it); return {it, true}; } } else { new_hash_table[hash] = prev(new_all_pairs.end()); return {new_hash_table[hash], true}; } } std::pair insert(const std::pair& tmp) { return emplace(tmp); } std::pair insert(std::pair&& tmp) { return emplace(std::move(tmp)); } template void insert(InputIterator begin, InputIterator end) { for (; begin != end; ++begin) { insert(*begin); } } iterator erase(const Key& key) { return erase(find(key)); } iterator erase(iterator it1) { auto it = it1.it; size_t hash = GetBucketIdx(*it); if (new_hash_table[hash] != it) { auto i = std::next(it); new_all_pairs.erase(it); return i; } else { if (GetBucketIdx(*std::next(it)) == hash) { auto i = std::next(it); new_all_pairs.erase(it); new_hash_table[hash] = i; return i; } else { auto i = std::next(it); new_all_pairs.erase(it); new_hash_table[hash] = new_all_pairs.end(); return i; } } } iterator erase(iterator begin, iterator end) { for (; begin != end;) { begin = erase(begin); } return end; } const_iterator erase(const_iterator begin, const_iterator end) { for (; begin != end; ++begin) { erase(begin); } return end; } iterator find(const Key& key) { size_t hash = GetBucketIdx(key); if (new_hash_table[hash] != new_all_pairs.end()) { auto i = new_hash_table[hash]; while (i != new_all_pairs.end() && GetBucketIdx(*i) == hash) { if (equal_(i->pair.first, key)) break; ++i; } if (i != new_all_pairs.end() && equal_(i->pair.first, key)) { return i; } else { return end(); } } else { return end(); } } const_iterator find(const Key& key) const { return const_cast(*this).find(key); } void rehash(size_t count) { if (count <= new_hash_table.size()) return; std::vector v(count, new_all_pairs.end()); for (auto it = begin_(); it != end_(); ++it) { auto& i = *it; size_t hash = hash_(i.pair.first); if (v[hash % v.size()] != new_all_pairs.end()) { new_all_pairs.relink(v[hash % v.size()], it); } else { v[hash % v.size()] = it; } } std::swap(new_hash_table, v); } void reserve(size_t count) { rehash(count); } float load_factor() const { return static_cast(size()) / new_hash_table.size(); } float max_load_factor() const { return max_load_factor_; } void max_load_factor(float ml) { max_load_factor_ = ml; } iterator begin() { return new_all_pairs.begin(); } iterator end() { return new_all_pairs.end(); } new_iterator begin_() { return new_all_pairs.begin(); } new_iterator end_() { return new_all_pairs.end(); } const_iterator begin() const { return const_iterator(const_cast(new_all_pairs).begin()); } const_iterator end() const { return const_iterator(const_cast(new_all_pairs).end()); } const_iterator cbegin() const { return const_iterator(const_cast(new_all_pairs).begin()); } const_iterator cend() const { return const_iterator(const_cast(new_all_pairs).end()); } reverse_iterator rbegin() { return reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(cend()); } const_reverse_iterator rend() const { return const_reverse_iterator(cbegin()); } const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); } const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); } private: Hash hash_; Equal equal_; float max_load_factor_; };