From 5c305acc9c1052e62786e6f6523fc50cc47d4aff Mon Sep 17 00:00:00 2001 From: Aydar Asadullin Date: Wed, 1 Mar 2023 00:53:50 +0300 Subject: [PATCH] deleting data from hash_map --- HashMap.h | 358 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 358 insertions(+) diff --git a/HashMap.h b/HashMap.h index e69de29..ff59371 100644 --- a/HashMap.h +++ b/HashMap.h @@ -0,0 +1,358 @@ +#pragma once + +#include +#include +#include +#include + +template > +class HashMap { + using ElementType = std::pair; + + struct ElementHash { + std::unique_ptr element = nullptr; + size_t hash = 0; + + ElementHash() {} + + ElementHash(ElementType element, size_t hash) : element(std::make_unique(element)), hash(hash) {} + }; + +public: + class iterator { + public: + iterator() : hm_(nullptr), index_(0) {} + + iterator(HashMap *hm, size_t index) : hm_(hm), index_(index) {} + + ElementType &operator*() const { + return *hm_->vec_[index_].element; + } + + ElementType *operator->() const { + return (hm_->vec_[index_].element).get(); + } + + iterator &operator=(iterator other) { + if (this != &other) { + hm_ = other.hm_; + index_ = other.index_; + } + return *this; + } + + iterator &operator++() { + ++index_; + index_ = hm_->next_bucket(index_); + return *this; + } + + iterator operator++(int) { + iterator tmp(hm_, index_); + ++index_; + index_ = hm_->next_bucket(index_); + return tmp; + } + + bool operator==(const iterator &other) const { + return hm_ == other.hm_ && index_ == other.index_; + } + + bool operator!=(const iterator &other) const { + return !(*this == other); + } + + private: + HashMap *hm_; + size_t index_; + }; + + class const_iterator { + public: + const_iterator() : hm_(nullptr), index_(0) {} + + const_iterator(HashMap const *hm, size_t index) : hm_(hm), index_(index) {} + + const ElementType &operator*() const { + return *hm_->vec_[index_].element; + } + + const ElementType *operator->() const { + return (hm_->vec_[index_].element).get(); + } + + const_iterator &operator=(const_iterator other) { + if (this != &other) { + hm_ = other.hm_; + index_ = other.index_; + } + return *this; + } + + const_iterator &operator++() { + ++index_; + index_ = hm_->next_bucket(index_); + return *this; + } + + const_iterator operator++(int) { + const_iterator tmp(hm_, index_); + ++index_; + index_ = hm_->next_bucket(index_); + return tmp; + } + + bool operator==(const const_iterator &other) const { + return hm_ == other.hm_ && index_ == other.index_; + } + + bool operator!=(const const_iterator &other) const { + return !(*this == other); + } + + private: + HashMap const *hm_; + size_t index_; + }; + + HashMap(Hash hasher = Hash()) : hasher_(hasher) { + vec_.resize(capacity_); + } + + template + HashMap(Forwarditerator begin, Forwarditerator end, Hash hasher = Hash()): hasher_(hasher) { + vec_.resize(capacity_); + while (begin != end) { + insert(std::make_pair((*begin).first, (*begin).second)); + begin++; + } + } + + HashMap(std::initializer_list initializerList, Hash hasher = Hash()) { + vec_.resize(capacity_); + for (const auto &[key, value]: initializerList) { + insert({key, value}); + } + } + + HashMap(const HashMap &other) { + hasher_ = other.hasher_; + H = other.H; + vec_.clear(); + capacity_ = other.capacity_; + vec_.clear(); + vec_.resize(capacity_); + auto begin_iterator = other.begin(); + auto end_iterator = other.end(); + while (begin_iterator != end_iterator) { + insert(std::make_pair((*begin_iterator).first, (*begin_iterator).second)); + begin_iterator++; + } + } + + ~HashMap() { + clear(); + } + + HashMap &operator=(const HashMap &other) { + if (this == &other) { + return *this; + } + clear(); + hasher_ = other.hasher_; + H = other.H; + capacity_ = other.capacity_; + vec_.clear(); + vec_.resize(capacity_); + auto begin_iterator = other.begin(); + auto end_iterator = other.end(); + while (begin_iterator != end_iterator) { + insert(std::make_pair((*begin_iterator).first, (*begin_iterator).second)); + begin_iterator++; + } + return *this; + } + + + iterator begin() { // NOLINT + return iterator(this, next_bucket(0)); + } + + iterator end() { // NOLINT + return iterator(this, capacity_); + } + + const_iterator begin() const { // NOLINT + return const_iterator(this, next_bucket(0)); + } + + const_iterator end() const { // NOLINT + return const_iterator(this, capacity_); + } + + [[nodiscard]] size_t size() const { + return size_; + } + + [[nodiscard]] bool empty() const { + return size() == 0; + } + + Hash hash_function() const { + return hasher_; + } + + + void insert(ElementType element) { + if (find(element.first) != end()) { + return; + } + ElementHash element_hash = ElementHash(element, hasher_(element.first) % capacity_); + size_t begin = element_hash.hash; + size_t pos = begin; + while (vec_[pos].element != nullptr) { + pos = sum(pos, 1); + } + while (distance(begin, pos) >= H) { + bool found_swap = false; + while (true) { + size_t now = subtract(pos, 1); + for (size_t i = 0; i < H - 1; ++i) { + if (distance(vec_[now].hash, pos) < H) { + found_swap = true; + std::swap(vec_[now], vec_[pos]); + pos = now; + break; + } + now = subtract(now, 1); + } + if (found_swap) { + break; + } + H *= 2; + } + } + vec_[pos] = std::move(element_hash); + size_ += 1; + if (load_factor() >= max_load_factor) { + rebuild(); + } + } + + void erase(KeyType key) { + size_t begin = hasher_(key) % capacity_; + size_t pos = begin; + for (size_t i = 0; i < H; ++i) { + if (vec_[pos].element != nullptr && key == vec_[pos].element->first) { + vec_[pos].element = nullptr; + size_--; + return; + } + pos = sum(pos, 1); + } + } + + iterator find(KeyType key) { + size_t begin = hasher_(key) % capacity_; + size_t pos = begin; + for (size_t i = 0; i < H; ++i) { + if (vec_[pos].element != nullptr && key == vec_[pos].element->first) { + return iterator(this, pos); + } + pos = sum(pos, 1); + } + return end(); + } + + const_iterator find(KeyType key) const { + size_t begin = hasher_(key) % capacity_; + size_t pos = begin; + for (size_t i = 0; i < H; ++i) { + if (vec_[pos].element != nullptr && key == vec_[pos].element->first) { + return const_iterator(this, pos); + } + pos = sum(pos, 1); + } + return end(); + } + + ValueType &operator[](KeyType key) { + auto it = find(key); + if (it == end()) { + insert(std::make_pair(key, ValueType())); + it = find(key); + } + return it->second; + } + + const ValueType &at(KeyType key) const { + auto it = find(key); + if (it == end()) { + throw std::out_of_range("No ElementType at this key"); + } + return it->second; + } + + void clear() { + size_ = 0; + for (size_t i = 0; i < capacity_; ++i) { + vec_[i].element = nullptr; + } + } + + +private: + size_t next_bucket(size_t index) const { + while (index != capacity_ && vec_[index].element == nullptr) { + index++; + } + return index; + } + + size_t sum(size_t a, size_t b) const { + size_t c = a + b; + if (c >= capacity_) { + return c - capacity_; + } + return c; + } + + size_t subtract(size_t a, size_t b) const { + if (a >= b) { + return a - b; + } else { + return a + capacity_ - b; + } + } + + size_t distance(size_t beg, size_t end) const { + return subtract(end, beg); + } + + double load_factor() const { + return (double) size_ / capacity_; + } + + void rebuild() { + std::vector elements; + for (auto element: *this) { + elements.push_back(element); + } + clear(); + H = H_begin_value; + capacity_ *= capacity_multiplier; + vec_.resize(capacity_); + for (auto element: elements) { + insert(element); + } + } + + std::vector vec_; + Hash hasher_; + size_t capacity_ = 64; + size_t size_ = 0; + const size_t H_begin_value = 2; + size_t H = H_begin_value; + const double capacity_multiplier = 2.0; + const double max_load_factor = 0.90; +};