|
| 1 | +/** |
| 2 | + * Created by Liam Huang (Liam0205) on 2018/08/14. |
| 3 | + * This is an old test file for hash_map, created by Liam. |
| 4 | + * Just for showing the inner logic for hash_map class template. |
| 5 | + * Original posted on: |
| 6 | + * https://github.com/Liam0205/leetcode/tree/master/met/hash_map.cc |
| 7 | + */ |
| 8 | + |
| 9 | +#include <iostream> |
| 10 | +#include <utility> |
| 11 | +#include <vector> |
| 12 | +#include <functional> |
| 13 | +#include <memory> |
| 14 | + |
| 15 | +template <typename Key, typename T, typename Hash = std::hash<Key>> |
| 16 | +class hash_map { |
| 17 | + public: |
| 18 | + using key_type = Key; |
| 19 | + using mapped_type = T; |
| 20 | + using value_type = std::pair<const key_type, mapped_type>; |
| 21 | + using size_type = size_t; |
| 22 | + using hasher = std::hash<Key>; |
| 23 | + |
| 24 | + private: // helper |
| 25 | + using wrapper = std::shared_ptr<value_type>; |
| 26 | + |
| 27 | + public: // constructor |
| 28 | + hash_map() { |
| 29 | + container_.resize(primes_[size_level_]); |
| 30 | + } |
| 31 | + |
| 32 | + public: // capacity |
| 33 | + bool empty() const { return empty_; } |
| 34 | + size_type size() const { return size_; } |
| 35 | + size_type max_size() const { return primes_[size_level_]; } |
| 36 | + |
| 37 | + public: // find and modify |
| 38 | + mapped_type& operator[](const key_type& key) { |
| 39 | + auto hashed = find_hash(key); |
| 40 | + if (not(container_[hashed]) and construct_new_on_position(hashed, key) and |
| 41 | + load_factor() > max_load_factor()) { |
| 42 | + expand(); |
| 43 | + } |
| 44 | + return container_[hashed]->second; |
| 45 | + } |
| 46 | + |
| 47 | + public: // hash policy |
| 48 | + double load_factor() const { return static_cast<double>(size()) / max_size(); } |
| 49 | + double max_load_factor() const { return max_load_factor_; } |
| 50 | + void expand() const { |
| 51 | + ++size_level_; |
| 52 | + std::vector<wrapper> temp; |
| 53 | + temp.resize(primes_[size_level_]); |
| 54 | + for (auto w : container_) { |
| 55 | + if (nullptr != w) { |
| 56 | + auto hashed = find_hash(w->first); |
| 57 | + temp[hashed] = w; |
| 58 | + } |
| 59 | + } |
| 60 | + container_ = std::move(temp); |
| 61 | + } |
| 62 | + |
| 63 | + private: // helper functions |
| 64 | + size_type find_hash(const key_type& key) const { |
| 65 | + const size_t csz = container_.size(); |
| 66 | + size_t count = 0; |
| 67 | + size_t hashed = hasher_(key) % csz; |
| 68 | + while (nullptr != container_[hashed] and container_[hashed]->first != key) { |
| 69 | + hashed = (hashed + ++count) % csz; |
| 70 | + } |
| 71 | + return hashed; |
| 72 | + } |
| 73 | + bool construct_new_on_position(const size_type pos, const key_type& key) { |
| 74 | + empty_ = false; |
| 75 | + ++size_; |
| 76 | + container_[pos] = std::make_shared<value_type>(std::make_pair(key, mapped_type())); |
| 77 | + return true; |
| 78 | + } |
| 79 | + |
| 80 | + private: |
| 81 | + const hasher hasher_ = hasher(); |
| 82 | + mutable size_t size_level_ = 0; |
| 83 | + mutable std::vector<wrapper> container_; |
| 84 | + static const size_t primes_[]; |
| 85 | + bool empty_ = true; |
| 86 | + size_type size_ = 0; |
| 87 | + double max_load_factor_ = 0.75; |
| 88 | +}; |
| 89 | +template <typename Key, typename T, typename Hash> |
| 90 | +const size_t hash_map<Key, T, Hash>::primes_[] = {7, 17, 29, 53, 101, 211, 401, 809, 1601, 3203}; // ... |
| 91 | + |
| 92 | +int main() { |
| 93 | + hash_map<int, int> test; |
| 94 | + test[1]; |
| 95 | + test[2] = 2; |
| 96 | + std::cout << test[1] << ' ' << test[2] << std::endl; |
| 97 | + return 0; |
| 98 | +} |
0 commit comments