diff --git a/README.md b/README.md index 190b1c3..1406de2 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Имя студента -*Пожалуйста, добавьте вместо курсивного текста своё ФИО.* +*Усанов Илья Владиславович* ## Описание задания diff --git a/src/hash_table.cpp b/src/hash_table.cpp index a581cb3..6dc1eed 100644 --- a/src/hash_table.cpp +++ b/src/hash_table.cpp @@ -4,82 +4,122 @@ namespace itis { - int HashTable::hash(int key) const { - return utils::hash(key, static_cast(buckets_.size())); - } + int HashTable::hash(int key) const { + return utils::hash(key, static_cast(buckets_.size())); + } + + HashTable::HashTable(int capacity, double load_factor) : load_factor_{load_factor} { + if (capacity <= 0) { + throw std::logic_error("hash table capacity must be greater than zero"); + } + + if (load_factor <= 0.0 || load_factor > 1.0) { + throw std::logic_error("hash table load factor must be in range [0...1]"); + } + + buckets_.resize(capacity); + } + + std::optional HashTable::Search(int key) const { + int hashCode = hash(key); + + for(auto elem : buckets_[hashCode]){ + if(elem.first == key){ + return elem.second; + } + } + + return std::nullopt; + } + + void HashTable::Put(int key, const std::string &value) { + int hashCode = hash(key); + + if(ContainsKey(key)){ + for(auto i = buckets_[hashCode].begin(); i != buckets_[hashCode].end(); i++){ + if(i->first == key){ + i->second = value; + } + } + } + + if(!ContainsKey(key)){ + buckets_[hashCode].push_back({key, value}); + num_keys_++; + } + + if (static_cast(num_keys_) / buckets_.size() >= load_factor_) { + std::vector newBuckets_(capacity() * kGrowthCoefficient); + + for(auto elem : buckets_){ + for(auto pair : elem){ + newBuckets_[utils::hash(pair.first, newBuckets_.size())].push_back(pair); + } + } + + buckets_.clear(); + buckets_.shrink_to_fit(); + buckets_ = newBuckets_; + } + } + + std::optional HashTable::Remove(int key) { + int hashCode = hash(key); + + if(ContainsKey(key)){ + for(auto i = buckets_[hashCode].begin(); i != buckets_[hashCode].end(); i++){ + if(i->first == key){ + auto deletedItem = i->second; + buckets_[hashCode].erase(i); + num_keys_--; + + return deletedItem; + } + } + + } - HashTable::HashTable(int capacity, double load_factor) : load_factor_{load_factor} { - if (capacity <= 0) { - throw std::logic_error("hash table capacity must be greater than zero"); + return std::nullopt; } - if (load_factor <= 0.0 || load_factor > 1.0) { - throw std::logic_error("hash table load factor must be in range [0...1]"); + bool HashTable::ContainsKey(int key) const { + return Search(key).has_value(); } - // Tip: allocate hash-table buckets - } + bool HashTable::empty() const { + return size() == 0; + } - std::optional HashTable::Search(int key) const { - // Tip: compute hash code (index) and use linear search - return std::nullopt; - } + int HashTable::size() const { + return num_keys_; + } - void HashTable::Put(int key, const std::string &value) { - // Tip 1: compute hash code (index) to determine which bucket to use - // Tip 2: consider the case when the key exists (read the docs in the header file) + int HashTable::capacity() const { + return static_cast(buckets_.size()); + } - if (static_cast(num_keys_) / buckets_.size() >= load_factor_) { - // Tip 3: recompute hash codes (indices) for key-value pairs (create a new hash-table) - // Tip 4: use utils::hash(key, size) to compute new indices for key-value pairs + double HashTable::load_factor() const { + return load_factor_; } - } - - std::optional HashTable::Remove(int key) { - // Tip 1: compute hash code (index) to determine which bucket to use - // TIp 2: find the key-value pair to remove and make a copy of value to return - return std::nullopt; - } - - bool HashTable::ContainsKey(int key) const { - // Note: uses Search(key) which is not initially implemented - return Search(key).has_value(); - } - - bool HashTable::empty() const { - return size() == 0; - } - - int HashTable::size() const { - return num_keys_; - } - - int HashTable::capacity() const { - return static_cast(buckets_.size()); - } - - double HashTable::load_factor() const { - return load_factor_; - } - - std::unordered_set HashTable::keys() const { - std::unordered_set keys(num_keys_); - for (const auto &bucket : buckets_) { - for (const auto &[key, _] : bucket) { - keys.insert(key); - } + + std::unordered_set HashTable::keys() const { + std::unordered_set keys(num_keys_); + for (const auto &bucket : buckets_) { + for (const auto &[key, _] : bucket) { + keys.insert(key); + } + } + return keys; } - return keys; - } - - std::vector HashTable::values() const { - std::vector values; - for (const auto &bucket : buckets_) { - for (const auto &[_, value] : bucket) { - values.push_back(value); - } + + std::vector HashTable::values() const { + std::vector values; + for (const auto &bucket : buckets_) { + for (const auto &[_, value] : bucket) { + values.push_back(value); + } + } + return values; } - return values; - } } // namespace itis \ No newline at end of file