Advertisement
leviathan0117

HashMap

Mar 2nd, 2021 (edited)
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.24 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <queue>
  5. #include <list>
  6. #include <iterator>
  7.  
  8.  
  9. template<class KeyType, class ValueType, class Hash = std::hash<KeyType> >
  10. class HashMap {
  11. private:
  12.     const size_t max_buckets = 3; // should be prime
  13.     struct element {
  14.         std::pair<const KeyType, ValueType> pair;
  15.         element() = default;
  16.         element(const element& other) = default;
  17.         element(element&& other) = default;
  18.         element& operator=(const element& other) {
  19.             pair.second = other.pair.second;
  20.             return *this;
  21.         }
  22.         element& operator=(element&& other) {
  23.             pair = other.pair;
  24.             return *this;
  25.         }
  26.     };
  27.     std::list<size_t> used_buckets_list;
  28.     std::vector<std::list<element>> data;
  29.     std::vector<std::list<size_t>::iterator> list_pointers;
  30.     Hash hasher;
  31.     size_t num_objects;
  32.  
  33.     size_t shrink_hash(size_t hash) const {
  34.         return hash % max_buckets;
  35.     }
  36.  
  37. public:
  38.     HashMap() {
  39.         num_objects = 0;
  40.         data.resize(max_buckets + 1);
  41.         list_pointers.resize(max_buckets + 1); // +1 is for iterators
  42.     }
  43.  
  44.     HashMap(const Hash input_hasher): hasher(input_hasher) {
  45.         num_objects = 0;
  46.         data.resize(max_buckets + 1);
  47.         list_pointers.resize(max_buckets + 1); // +1 is for iterators
  48.     }
  49.  
  50.     HashMap(const HashMap& other):
  51.             data(other.data),
  52.             list_pointers(other.list_pointers),
  53.             used_buckets_list(other.used_buckets_list),
  54.             num_objects(other.num_objects),
  55.             hasher(other.hasher)
  56.     {}
  57.     HashMap(HashMap&& other) :
  58.             data(std::move(other.data)),
  59.             list_pointers(other.list_pointers),
  60.             used_buckets_list(std::move(other.ids)),
  61.             num_objects(other.num_objects),
  62.             hasher(other.hasher)
  63.     {}
  64.  
  65.     HashMap& operator = (const HashMap& other) {
  66.         data = other.data;
  67.         list_pointers = other.list_pointers;
  68.         used_buckets_list = other.used_buckets_list;
  69.         num_objects = other.num_objects;
  70.         hasher = other.hasher;
  71.         return *this;
  72.     }
  73.     HashMap& operator = (HashMap&& other) {
  74.         data = std::move(other.data);
  75.         list_pointers = std::move(other.list_pointers);
  76.         used_buckets_list = std::move(other.used_buckets_list);
  77.         num_objects = other.num_objects;
  78.         hasher = other.hasher;
  79.         return *this;
  80.     }
  81.  
  82.     template<class Container = HashMap>
  83.     HashMap(typename Container::iterator first, typename Container::iterator last) {
  84.         num_objects = 0;
  85.         data.resize(max_buckets + 1);
  86.         list_pointers.resize(max_buckets + 1); // +1 is for iterators
  87.  
  88.         for (auto it = first; it != last; ++it) {
  89.             insert(*it);
  90.         }
  91.     }
  92.     template<class Container = HashMap>
  93.     HashMap(typename Container::iterator first, typename Container::iterator last, const Hash input_hasher): hasher(input_hasher)  {
  94.         num_objects = 0;
  95.         data.resize(max_buckets + 1);
  96.         list_pointers.resize(max_buckets + 1); // +1 is for iterators
  97.  
  98.         for (auto it = first; it != last; ++it) {
  99.             insert(*it);
  100.         }
  101.     }
  102.     template<class Container = HashMap>
  103.     HashMap(typename Container::const_iterator first, typename Container::const_iterator last) {
  104.         num_objects = 0;
  105.         data.resize(max_buckets + 1);
  106.         list_pointers.resize(max_buckets + 1); // +1 is for iterators
  107.  
  108.         for (auto it = first; it != last; ++it) {
  109.             insert(*it);
  110.         }
  111.     }
  112.     template<class Container = HashMap>
  113.     HashMap(typename Container::const_iterator first, typename Container::const_iterator last, const Hash input_hasher): hasher(input_hasher)  {
  114.         num_objects = 0;
  115.         data.resize(max_buckets + 1);
  116.         list_pointers.resize(max_buckets + 1); // +1 is for iterators
  117.  
  118.         for (auto it = first; it != last; ++it) {
  119.             insert(*it);
  120.         }
  121.     }
  122.  
  123.     HashMap(std::initializer_list<std::pair<KeyType, ValueType>> _data) {
  124.         num_objects = 0;
  125.         data.resize(max_buckets + 1);
  126.         list_pointers.resize(max_buckets + 1); // +1 is for iterators
  127.  
  128.         for (auto elem: _data) {
  129.             insert(elem);
  130.         }
  131.     }
  132.     HashMap(std::initializer_list<std::pair<KeyType, ValueType>> _data, const Hash input_hasher): hasher(input_hasher)  {
  133.         num_objects = 0;
  134.         data.resize(max_buckets + 1);
  135.         list_pointers.resize(max_buckets + 1); // +1 is for iterators
  136.  
  137.         for (auto elem : _data) {
  138.             insert(elem);
  139.         }
  140.     }
  141.  
  142.     size_t size() const {
  143.         return num_objects;
  144.     }
  145.  
  146.     bool empty() const {
  147.         if (num_objects == 0) {
  148.             return true;
  149.         } else {
  150.             return false;
  151.         }
  152.     }
  153.  
  154.     size_t hash_function(const ValueType value) const {
  155.         return hasher(value);
  156.     }
  157.  
  158.     void insert(const std::pair<const KeyType, ValueType> input) {
  159.         size_t bucket_id = shrink_hash(hasher(input.first));
  160.  
  161.         for (auto it = data[bucket_id].begin(); it != data[bucket_id].end(); ++it) {
  162.             if (it->pair.first == input.first) {
  163.                 return;
  164.             }
  165.         }
  166.  
  167.         if (data[bucket_id].empty()) {
  168.             used_buckets_list.push_back(bucket_id);
  169.             list_pointers[bucket_id] = std::prev(used_buckets_list.end());
  170.         }
  171.         data[bucket_id].push_back({{input.first, input.second}});
  172.         ++num_objects;
  173.     }
  174.  
  175.     void erase(const KeyType key) {
  176.         size_t bucket_id = shrink_hash(hasher(key));
  177.  
  178.         if (data[bucket_id].empty()) {
  179.             return;
  180.         }
  181.  
  182.         if (data[bucket_id].size() == 1) {
  183.             if (data[bucket_id].front().pair.first == key) {
  184.                 used_buckets_list.erase(list_pointers[bucket_id]);
  185.                 data[bucket_id].pop_front();
  186.                 --num_objects;
  187.             }
  188.         } else {
  189.             for (auto it = data[bucket_id].begin(); it != data[bucket_id].end(); ++it) {
  190.                 if (it->pair.first == key) {
  191.                     data[bucket_id].erase(it);
  192.                     --num_objects;
  193.                     return;
  194.                 }
  195.             }
  196.         }
  197.     }
  198.  
  199.     ValueType &operator[](const KeyType key) {
  200.         size_t bucket_id = shrink_hash(hasher(key));
  201.  
  202.         for (auto it = data[bucket_id].begin(); it != data[bucket_id].end(); ++it) {
  203.             if (it->pair.first == key) {
  204.                 return it->pair.second;
  205.             }
  206.         }
  207.         if (data[bucket_id].empty()) {
  208.             used_buckets_list.push_back(bucket_id);
  209.             list_pointers[bucket_id] = std::prev(used_buckets_list.end());
  210.         }
  211.         data[bucket_id].push_back({{key, ValueType()}});
  212.         ++num_objects;
  213.         return data[bucket_id].back().pair.second;
  214.     }
  215.  
  216.     const ValueType & at(KeyType key) const {
  217.         size_t bucket_id = shrink_hash(hasher(key));
  218.  
  219.         for (auto it = data[bucket_id].begin(); it != data[bucket_id].end(); ++it) {
  220.             if (it->pair.first == key) {
  221.                 return it->pair.second;
  222.             }
  223.         }
  224.         throw std::out_of_range("bad key");
  225.     }
  226.  
  227.     void clear() {
  228.         for (auto bucket_id : used_buckets_list) {
  229.             data[bucket_id].clear();
  230.         }
  231.         num_objects = 0;
  232.         used_buckets_list.clear();
  233.     }
  234.  
  235.     Hash hash_function() const {
  236.         return hasher;
  237.     }
  238.  
  239.     class iterator {
  240.     private:
  241.         std::vector<std::list<element>> *data;
  242.         std::list<size_t> *used_buckets_list;
  243.  
  244.         std::list<size_t>::iterator  current_bucket_iterator; // used_buckets_list
  245.         typename std::list<element>::iterator  in_bucket_iterator; // in data list
  246.  
  247.     public:
  248.         iterator() = default;
  249.         iterator(const iterator &) = default;
  250.         iterator(iterator &&) = default;
  251.         iterator(
  252.                 std::vector<std::list<element>> *input_data,
  253.                 std::list<size_t>::iterator  input_current_bucket_iterator,
  254.                 typename std::list<element>::iterator  input_in_bucket_iterator,
  255.                 std::list<size_t> *input_used_buckets_list
  256.         ) :
  257.                 data(input_data),
  258.                 current_bucket_iterator(input_current_bucket_iterator),
  259.                 in_bucket_iterator(input_in_bucket_iterator),
  260.                 used_buckets_list(input_used_buckets_list){}
  261.  
  262.         iterator &operator++() {
  263.             ++in_bucket_iterator;
  264.             if (in_bucket_iterator == (*data)[*current_bucket_iterator].end()) {
  265.                 ++current_bucket_iterator;
  266.                 if (current_bucket_iterator != (*used_buckets_list).end())
  267.                     in_bucket_iterator = (*data)[*current_bucket_iterator].begin();
  268.                 else
  269.                     in_bucket_iterator = (*data)[*(*used_buckets_list).begin()].begin();
  270.             }
  271.             return *this;
  272.         }
  273.  
  274.         iterator operator++(int) {
  275.             auto temp = *this;
  276.             ++(*this);
  277.             return temp;
  278.         }
  279.  
  280.         std::pair<const KeyType, ValueType> operator*() const {
  281.             return in_bucket_iterator->pair;
  282.         }
  283.  
  284.         std::pair<const KeyType, ValueType> *operator->() const {
  285.             return &(in_bucket_iterator->pair);
  286.         }
  287.  
  288.         friend bool operator==(const iterator &it1,
  289.                                const iterator &it2) {
  290.             return it1.current_bucket_iterator == it2.current_bucket_iterator &&
  291.                    it1.in_bucket_iterator == it2.in_bucket_iterator;
  292.         }
  293.  
  294.         bool operator!=(const iterator &it1) const {
  295.             return !((*this) == it1);
  296.         }
  297.  
  298.         iterator& operator=(const iterator& other) {
  299.             data = other.data;
  300.             used_buckets_list = other.used_buckets_list;
  301.             current_bucket_iterator = other.current_bucket_iterator;
  302.             in_bucket_iterator = other.in_bucket_iterator;
  303.             return *this;
  304.         }
  305.  
  306.         iterator& operator=(iterator&& other) {
  307.             data = other.data;
  308.             used_buckets_list = other.used_buckets_list;
  309.             current_bucket_iterator = other.current_bucket_iterator;
  310.             in_bucket_iterator = other.in_bucket_iterator;
  311.             return *this;
  312.         }
  313.  
  314.     };
  315.  
  316.     class const_iterator {
  317.     private:
  318.         const std::vector<std::list<element>> *data;
  319.         const std::list<size_t> *used_buckets_list;
  320.  
  321.         std::list<size_t>::const_iterator  current_bucket_iterator; // used_buckets_list
  322.         typename std::list<element>::const_iterator  in_bucket_iterator; // in data list
  323.  
  324.     public:
  325.         const_iterator() = default;
  326.         const_iterator(const const_iterator &) = default;
  327.         const_iterator(const_iterator &&) = default;
  328.         const_iterator(
  329.                 const std::vector<std::list<element>> *input_data,
  330.                 std::list<size_t>::const_iterator  input_current_bucket_iterator,
  331.                 typename std::list<element>::const_iterator  input_in_bucket_iterator,
  332.                 const std::list<size_t> *input_used_buckets_list
  333.         ) :
  334.                 data(input_data),
  335.                 current_bucket_iterator(input_current_bucket_iterator),
  336.                 in_bucket_iterator(input_in_bucket_iterator),
  337.                 used_buckets_list(input_used_buckets_list){}
  338.  
  339.         const_iterator &operator++() {
  340.             ++in_bucket_iterator;
  341.             if (in_bucket_iterator == (*data)[*current_bucket_iterator].end()) {
  342.                 ++current_bucket_iterator;
  343.                 if (current_bucket_iterator != (*used_buckets_list).end())
  344.                     in_bucket_iterator = (*data)[*current_bucket_iterator].begin();
  345.                 else
  346.                     in_bucket_iterator = (*data)[*(*used_buckets_list).begin()].begin();
  347.             }
  348.             return *this;
  349.         }
  350.  
  351.         const_iterator operator++(int) {
  352.             auto temp = *this;
  353.             ++(*this);
  354.             return temp;
  355.         }
  356.  
  357.         const std::pair<const KeyType, ValueType> operator*() const {
  358.             return in_bucket_iterator->pair;
  359.         }
  360.  
  361.         const std::pair<const KeyType, ValueType> *operator->() const {
  362.             return &(in_bucket_iterator->pair);
  363.         }
  364.  
  365.         friend bool operator==(const const_iterator &it1,
  366.                                const const_iterator &it2) {
  367.             return it1.current_bucket_iterator == it2.current_bucket_iterator &&
  368.                    it1.in_bucket_iterator == it2.in_bucket_iterator;
  369.         }
  370.  
  371.         bool operator!=(const const_iterator &it1) const {
  372.             return !((*this) == it1);
  373.         }
  374.  
  375.         const_iterator& operator=(const const_iterator& other) {
  376.             data = other.data;
  377.             used_buckets_list = other.used_buckets_list;
  378.             current_bucket_iterator = other.current_bucket_iterator;
  379.             in_bucket_iterator = other.in_bucket_iterator;
  380.             return *this;
  381.         }
  382.  
  383.         const_iterator& operator=(const_iterator&& other) {
  384.             data = other.data;
  385.             used_buckets_list = other.used_buckets_list;
  386.             current_bucket_iterator = other.current_bucket_iterator;
  387.             in_bucket_iterator = other.in_bucket_iterator;
  388.             return *this;
  389.         }
  390.     };
  391.  
  392.     iterator begin() {
  393.         if (num_objects != 0) {
  394.             return iterator{&data, used_buckets_list.begin(), data[*used_buckets_list.begin()].begin(), &used_buckets_list};
  395.         }
  396.         return iterator{&data, used_buckets_list.begin(), data[max_buckets].begin(), &used_buckets_list};
  397.     }
  398.  
  399.     iterator end() {
  400.         if (num_objects != 0) {
  401.             return iterator{&data, used_buckets_list.end(), data[*used_buckets_list.begin()].begin(), &used_buckets_list};
  402.         }
  403.         return iterator{&data, used_buckets_list.begin(), data[max_buckets].begin(), &used_buckets_list};
  404.     }
  405.  
  406.     const_iterator begin() const {
  407.         if (num_objects != 0) {
  408.             return const_iterator{&data, used_buckets_list.begin(), data[*used_buckets_list.begin()].begin(), &used_buckets_list};
  409.         }
  410.         return const_iterator{&data, used_buckets_list.begin(), data[max_buckets].begin(), &used_buckets_list};
  411.     }
  412.  
  413.     const_iterator end() const {
  414.         if (num_objects != 0) {
  415.             return const_iterator{&data, used_buckets_list.end(), data[*used_buckets_list.begin()].begin(), &used_buckets_list};
  416.         }
  417.         return const_iterator{&data, used_buckets_list.begin(), data[max_buckets].begin(), &used_buckets_list};
  418.     }
  419.  
  420.     iterator find(KeyType key) {
  421.         size_t bucket_id = shrink_hash(hasher(key));
  422.  
  423.         for (auto it = data[bucket_id].begin(); it != data[bucket_id].end(); ++it) {
  424.             if (it->pair.first == key) {
  425.                 return iterator(&data, list_pointers[bucket_id], it, &used_buckets_list);
  426.             }
  427.         }
  428.         return end();
  429.     }
  430.  
  431.     const_iterator find(KeyType key) const {
  432.         size_t bucket_id = shrink_hash(hasher(key));
  433.  
  434.         for (auto it = data[bucket_id].begin(); it != data[bucket_id].end(); ++it) {
  435.             if (it->pair.first == key) {
  436.                 return const_iterator(&data, list_pointers[bucket_id], it, &used_buckets_list);
  437.             }
  438.         }
  439.         return end();
  440.     }
  441.  
  442. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement