Huffman Zipper  v-1.0
Data Compression and Decompression using Greedy Huffman Algorithm
HashMap.h
Go to the documentation of this file.
1 #pragma once
2 #include <vector>
3 
4 #include "HashCode.h"
5 #include "Constants.h"
6 
13 template <typename KeyType, typename ValueType>
14 class HashMap {
15 private:
16 
18  struct Entry {
19  KeyType key;
20  ValueType value;
22  };
23 
24  std::vector<Entry*> buckets;
25  int nBuckets;
26  int numEntries;
28 private:
29 
32 
34  void deleteBuckets(std::vector<Entry*>& buckets);
35 
44 
49  Entry* findEntry(int bucket, const KeyType& key) const;
50 
55  Entry* findEntry(int bucket, const KeyType& key, Entry*& parent) const;
56 
58  void deepCopy(const HashMap& src);
59 
60 public:
62  virtual ~HashMap();
63 
65  HashMap(const HashMap& src);
66 
68  HashMap& operator=(const HashMap& src);
69 
71  void clear();
72 
74  int size() const;
75 
77  bool isEmpty() const;
78 
80  void put(const KeyType& key, const ValueType& value);
81 
86  ValueType get(const KeyType& key) const;
87 
92  bool containsKey(const KeyType& key) const;
93 
98  void remove(const KeyType& key);
99 
107  ValueType& operator[](const KeyType& key);
108  ValueType operator[](const KeyType& key) const;
109 
110 
114  class iterator {
115  private:
116  const HashMap* map;
117  int bucket;
120  public:
121  iterator() {}
122 
123  iterator(const HashMap* map, bool end) {
124  this->map = map;
125  if (end) {
126  bucket = map->nBuckets;
127  current = nullptr;
128  }
129  else {
130  bucket = 0;
131  current = map->buckets.at(bucket);
132  while (current == nullptr && ++bucket < map->nBuckets) {
133  current = map->buckets.at(bucket);
134  }
135  }
136  }
137 
138  iterator(const iterator& it) {
139  map = it.map;
140  bucket = it.bucket;
141  current = it.current;
142  }
143 
145  current = current->next;
146  while (current == nullptr && ++bucket < map->nBuckets) {
147  current = map->buckets.at(bucket);
148  }
149  return *this;
150  }
151 
153  iterator copy(*this);
154  operator++();
155  return copy;
156  }
157 
158  bool operator==(const iterator& rhs) {
159  return map == rhs.map && bucket == rhs.bucket && current == rhs.current;
160  }
161 
162  bool operator!=(const iterator& rhs) {
163  return !(*this == rhs);
164  }
165 
167  return *current;
168  }
169 
171  return current;
172  }
173 
174  // iterator traits
176  using value_type = Entry;
177  using pointer = const Entry*;
178  using reference = const Entry&;
179  using iterator_category = std::forward_iterator_tag;
180  };
181 
182  iterator begin() const {
183  return iterator(this, false);
184  }
185 
186  iterator end() const {
187  return iterator(this, true);
188  }
189 };
190 
191 /************************************************************************/
192 /* implementation */
193 /************************************************************************/
194 
195 template <typename KeyType, typename ValueType>
197  if (nBuckets == 0) nBuckets = 1;
198  buckets = std::vector<Entry*>(nBuckets, nullptr);
199  this->nBuckets = nBuckets;
200  numEntries = 0;
201 }
202 
203 template <typename KeyType, typename ValueType>
204 void HashMap<KeyType, ValueType>::deleteBuckets(std::vector<Entry*>& buckets) {
205  for (int i = 0; i < buckets.size(); i++) {
206  Entry* current = buckets[i];
207  while (current != nullptr) {
208  Entry* np = current->next;
209  delete current;
210  current = np;
211  }
212  buckets[i] = nullptr;
213  }
214 }
215 
216 template <typename KeyType, typename ValueType>
218  std::vector<Entry*> oldBuckets = buckets;
219  createBuckets(oldBuckets.size() * 2 + 1);
220  for (int i = 0; i < oldBuckets.size(); i++) {
221  for (Entry* current = oldBuckets[i]; current != nullptr; current = current->next) {
222  put(current->key, current->value);
223  }
224  }
225  deleteBuckets(oldBuckets);
226 }
227 
228 template <typename KeyType, typename ValueType>
230 HashMap<KeyType, ValueType>::findEntry(int bucket, const KeyType& key) const {
231  Entry* parent;
232  return findEntry(bucket, key, parent);
233 }
234 
235 template <typename KeyType, typename ValueType>
237 HashMap<KeyType, ValueType>::findEntry(int bucket, const KeyType& key, Entry*& parent) const {
238  parent = nullptr;
239  Entry* current = buckets.at(bucket);
240  while (current != nullptr && key != current->key) {
241  parent = current;
242  current = current->next;
243  }
244  return current;
245 }
246 
247 template <typename KeyType, typename ValueType>
249  createBuckets(src.nBuckets);
250  for (int i = 0; i < src.nBuckets; i++) {
251  for (Entry* current = src.buckets.at(i); current != nullptr; current = current->next) {
252  put(current->key, current->value);
253  }
254  }
255 }
256 
257 template <typename KeyType, typename ValueType>
259  createBuckets(INITIAL_BUCKET_COUNT);
260 }
261 
262 template <typename KeyType, typename ValueType>
264  deleteBuckets(buckets);
265 }
266 
267 template <typename KeyType, typename ValueType>
269  deepCopy(src);
270 }
271 
272 template <typename KeyType, typename ValueType>
274  if (this != &src) {
275  clear();
276  deepCopy(src);
277  }
278  return *this;
279 }
280 
281 template <typename KeyType, typename ValueType>
283  return numEntries;
284 }
285 
286 template <typename KeyType, typename ValueType>
288  return size() == 0;
289 }
290 
291 template <typename KeyType, typename ValueType>
292 void HashMap<KeyType, ValueType>::put(const KeyType& key, const ValueType& value) {
293  (*this)[key] = value;
294 }
295 
296 template <typename KeyType, typename ValueType>
297 ValueType HashMap<KeyType, ValueType>::get(const KeyType& key) const {
298  Entry* current = findEntry(hashCode(key) % nBuckets, key);
299  if (current == nullptr) return ValueType();
300  return current->value;
301 }
302 
303 template <typename KeyType, typename ValueType>
304 bool HashMap<KeyType, ValueType>::containsKey(const KeyType& key) const {
305  return findEntry(hashCode(key) % nBuckets, key) != nullptr;
306 }
307 
308 template <typename KeyType, typename ValueType>
309 void HashMap<KeyType, ValueType>::remove(const KeyType& key) {
310  int bucket = hashCode(key) % nBuckets;
311  Entry* parent;
312  Entry* current = findEntry(bucket, key, parent);
313  if (current != nullptr) {
314  if (parent == nullptr) {
315  buckets[bucket] = current->next;
316  }
317  else {
318  parent->next = current->next;
319  }
320  delete current;
321  numEntries--;
322  }
323 }
324 
325 template <typename KeyType, typename ValueType>
327  deleteBuckets(buckets);
328  numEntries = 0;
329 }
330 
331 template <typename KeyType, typename ValueType>
332 ValueType& HashMap<KeyType, ValueType>::operator[](const KeyType& key) {
333  int bucket = hashCode(key) % nBuckets;
334  Entry* current = findEntry(bucket, key);
335  if (current == nullptr) {
336  if (numEntries > MAX_LOAD_PERCENTAGE * nBuckets / 100.0) {
337  expandAndRehash();
338  bucket = hashCode(key) % nBuckets;
339  }
340  current = new Entry;
341  current->key = key;
342  current->value = ValueType();
343  current->next = buckets[bucket];
344  buckets[bucket] = current;
345  numEntries++;
346  }
347  return current->value;
348 }
349 
350 template <typename KeyType, typename ValueType>
351 ValueType HashMap<KeyType, ValueType>::operator[](const KeyType& key) const {
352  return get(key);
353 }
This file exports the constants used in throughout the project.
constexpr auto MAX_LOAD_PERCENTAGE
Definition: Constants.h:11
constexpr auto INITIAL_BUCKET_COUNT
Constants for HashMap.
Definition: Constants.h:10
int hashCode(int key)
Returns a hash code for the specified key, which is always a nonnegative integer.
Definition: HashCode.cpp:9
This file contains prototype for the hashCode functions used in class HashMap.
Iterator support for class HashMap.
Definition: HashMap.h:114
iterator operator++(int)
Definition: HashMap.h:152
Entry * current
Current cell in bucket chain.
Definition: HashMap.h:118
int bucket
Index of current bucket
Definition: HashMap.h:117
Entry * operator->()
Definition: HashMap.h:170
iterator(const iterator &it)
Definition: HashMap.h:138
std::forward_iterator_tag iterator_category
Definition: HashMap.h:179
const HashMap * map
Pointer to the map
Definition: HashMap.h:116
iterator(const HashMap *map, bool end)
Definition: HashMap.h:123
iterator & operator++()
Definition: HashMap.h:144
bool operator!=(const iterator &rhs)
Definition: HashMap.h:162
bool operator==(const iterator &rhs)
Definition: HashMap.h:158
Entry operator*()
Definition: HashMap.h:166
This class implements an association between keys and values.
Definition: HashMap.h:14
int numEntries
Total number of entries.
Definition: HashMap.h:26
Entry * findEntry(int bucket, const KeyType &key) const
Finds a cell in the chain for the specified bucket that matches key.
Definition: HashMap.h:230
ValueType & operator[](const KeyType &key)
Selects the value associated with key.
Definition: HashMap.h:332
void remove(const KeyType &key)
removes any entry for key from this map.
Definition: HashMap.h:309
iterator begin() const
Definition: HashMap.h:182
Entry * findEntry(int bucket, const KeyType &key, Entry *&parent) const
Definition: HashMap.h:237
ValueType operator[](const KeyType &key) const
Definition: HashMap.h:351
void expandAndRehash()
Increases the buckets in the map and then rehashes all existing entries.
Definition: HashMap.h:217
void createBuckets(int nBuckets)
Creates vector of buckets to have nBuckets entries, each NULL.
Definition: HashMap.h:196
void deleteBuckets(std::vector< Entry * > &buckets)
Deletes all the cells in the linked lists contained in vector.
Definition: HashMap.h:204
int nBuckets
Total number of buckets.
Definition: HashMap.h:25
HashMap(const HashMap &src)
This copy constructor is to make a deep copy of HashMap.
Definition: HashMap.h:268
bool isEmpty() const
Definition: HashMap.h:287
ValueType get(const KeyType &key) const
Definition: HashMap.h:297
int size() const
Definition: HashMap.h:282
void deepCopy(const HashMap &src)
Creates deep copy of src HashMap.
Definition: HashMap.h:248
HashMap & operator=(const HashMap &src)
This operator= are defined assign from one map to another.
Definition: HashMap.h:273
HashMap()
Definition: HashMap.h:258
void clear()
Removes all entries from this map.
Definition: HashMap.h:326
virtual ~HashMap()
Definition: HashMap.h:263
iterator end() const
Definition: HashMap.h:186
std::vector< Entry * > buckets
Vector of pointer to Entry.
Definition: HashMap.h:24
void put(const KeyType &key, const ValueType &value)
Associates key with value in this map.
Definition: HashMap.h:292
bool containsKey(const KeyType &key) const
Definition: HashMap.h:304
Type definition for each cells in the bucket chain.
Definition: HashMap.h:18
KeyType key
Definition: HashMap.h:19
ValueType value
Definition: HashMap.h:20
Entry * next
Definition: HashMap.h:21