Advertisement
ludaludaed

HashTable

Oct 17th, 2022 (edited)
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.60 KB | None | 0 0
  1. #include <iostream>
  2.  
  3. template <class KeyType, class ValueType>
  4. struct Node {
  5.     KeyType key_;
  6.     ValueType value_;
  7.     Node<KeyType, ValueType> *next_{nullptr};
  8.  
  9.     Node(KeyType key, ValueType value) {
  10.         key_ = key;
  11.         value_ = value;
  12.     }
  13. };
  14.  
  15. template <class KeyType, class ValueType, class Func = std::hash<KeyType>>
  16. class HashTable {
  17.     size_t count_;
  18.     size_t capacity_;
  19.     Node<KeyType, ValueType> **entries_;
  20.     Func hash_function_;
  21.     double factor_;
  22.  
  23. public:
  24.     HashTable() {
  25.         capacity_ = 100;
  26.         factor_ = 0.5;
  27.         count_ = 0;
  28.         entries_ = new Node<KeyType, ValueType> *[capacity_];
  29.         for (int i = 0; i < capacity_; ++i) {
  30.             entries_[i] = nullptr;
  31.         }
  32.     }
  33.  
  34.     explicit HashTable(Func func) {
  35.         capacity_ = 100;
  36.         factor_ = 0.5;
  37.         count_ = 0;
  38.         entries_ = new Node<KeyType, ValueType> *[capacity_];
  39.         for (int i = 0; i < capacity_; ++i) {
  40.             entries_[i] = nullptr;
  41.         }
  42.         hash_function_ = func;
  43.     }
  44.  
  45.     HashTable(size_t size, double factor, Func func = std::hash<KeyType>()) {
  46.         capacity_ = size;
  47.         count_ = 0;
  48.         if (factor > 1 || factor <= 0) {
  49.             factor_ = 0.5;
  50.         } else {
  51.             factor_ = factor;
  52.         }
  53.         entries_ = new Node<KeyType, ValueType> *[size];
  54.         for (size_t i = 0; i < size; ++i) {
  55.             entries_[i] = nullptr;
  56.         }
  57.         hash_function_ = func;
  58.     }
  59.  
  60.     ~HashTable() {
  61.         for (int i = 0; i < capacity_; ++i) {
  62.             if (entries_[i] != nullptr) {
  63.                 clear(entries_[i]);
  64.             }
  65.         }
  66.         delete[] entries_;
  67.     }
  68.  
  69.     void insert(KeyType key, ValueType value) {
  70.         size_t hash = hash_function_(key);
  71.         size_t index = indexFor(hash, capacity_);
  72.  
  73.         auto current_node = entries_[index];
  74.         while (current_node != nullptr) {
  75.             if (hash_function_(current_node->key_) == hash && key == current_node->key_) {
  76.                 current_node->value_ = value;
  77.                 return;
  78.             }
  79.             current_node = current_node->next_;
  80.         }
  81.         ensureRehash();
  82.         index = indexFor(hash, capacity_);
  83.  
  84.         auto new_node = new Node<KeyType, ValueType>(key, value);
  85.         new_node->next_ = entries_[index];
  86.  
  87.         entries_[index] = new_node;
  88.         count_++;
  89.     }
  90.  
  91.     ValueType *find(KeyType key) {
  92.         size_t hash = hash_function_(key);
  93.         size_t index = indexFor(hash, capacity_);
  94.  
  95.         auto current_node = entries_[index];
  96.  
  97.         while (current_node != nullptr) {
  98.             if (hash_function_(current_node->key_) == hash && key == current_node->key_) {
  99.                 return &(current_node->value_);
  100.             }
  101.             current_node = current_node->next_;
  102.         }
  103.  
  104.         return nullptr;
  105.     }
  106.  
  107.     void erase(KeyType key) {
  108.         size_t hash = hash_function_(key);
  109.         size_t index = indexFor(hash, capacity_);
  110.  
  111.         Node<KeyType, ValueType> *prior_node = nullptr;
  112.         auto current_node = entries_[index];
  113.         while (current_node != nullptr) {
  114.             if (hash_function_(current_node->key_) == hash && key == current_node->key_) {
  115.                 if (prior_node == nullptr) {
  116.                     entries_[index] = entries_[index]->next_;
  117.                 } else {
  118.                     prior_node->next_ = current_node->next_;
  119.                 }
  120.                 delete current_node;
  121.                 count_--;
  122.                 return;
  123.             }
  124.             prior_node = current_node;
  125.             current_node = current_node->next_;
  126.         }
  127.     }
  128.  
  129.     Node<KeyType, ValueType> &operator[](uint64_t hash) {
  130.         if (hash < 0 || hash >= capacity_) {
  131.             throw std::out_of_range("");
  132.         }
  133.         if (entries_[hash] == nullptr) {
  134.             throw std::runtime_error("");
  135.         }
  136.         return *(entries_[hash]);
  137.     }
  138.  
  139.     Node<KeyType, ValueType> at(uint64_t hash) {
  140.         if (hash < 0 || hash >= capacity_) {
  141.             throw std::out_of_range("");
  142.         }
  143.         if (entries_[hash] == nullptr) {
  144.             throw std::runtime_error("");
  145.         }
  146.         return *(entries_[hash]);
  147.     }
  148.  
  149.     size_t size() const {
  150.         return count_;
  151.     }
  152.  
  153.     size_t capacity() const {
  154.         return capacity_;
  155.     }
  156.  
  157. private:
  158.     void clear(Node<KeyType, ValueType> *node) {
  159.         if (node == nullptr) {
  160.             return;
  161.         }
  162.         clear(node->next_);
  163.         delete node;
  164.     }
  165.  
  166.     void ensureRehash() {
  167.         if (count_ < capacity_ * factor_) {
  168.             return;
  169.         }
  170.         size_t new_capacity = capacity_ * 2;
  171.         auto new_entries = new Node<KeyType, ValueType> *[new_capacity];
  172.  
  173.         for (size_t i = 0; i < new_capacity; ++i) {
  174.             new_entries[i] = nullptr;
  175.         }
  176.  
  177.         for (size_t idx = 0; idx < capacity_; ++idx) {
  178.             if (entries_[idx] == nullptr) {
  179.                 continue;
  180.             }
  181.             auto current_node = entries_[idx];
  182.  
  183.             while (current_node != nullptr) {
  184.                 auto temp_node = current_node;
  185.                 current_node = current_node->next_;
  186.                 size_t rehash_idx = indexFor(hash_function_(temp_node->key_), new_capacity);
  187.                 temp_node->next_ = new_entries[rehash_idx];
  188.                 new_entries[rehash_idx] = temp_node;
  189.             }
  190.         }
  191.         capacity_ = new_capacity;
  192.         delete[] entries_;
  193.         entries_ = new_entries;
  194.     }
  195.  
  196.     size_t indexFor(size_t hash, size_t capacity) const {
  197.         return hash % capacity;
  198.     }
  199. };
  200.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement