-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path0003
795 lines (681 loc) · 27.1 KB
/
0003
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
#include <iostream>
#include <sstream>
#include <initializer_list>
// -----------------------------------------------------------------------------------------------
// Definition of simple dynamic array class
template <typename T>
class DynamicArray {
// The Dynamic Array has an initial capacity.
// If more elements will be added, there will be a reallocation with double capacity
static constexpr unsigned int InitialCapacity{ 8 };
// Internal data ------------------------------------------------------------------------------
T* data{}; // Dynamic Storage for Data
unsigned int numberOfElements{}; // Number of elements currently in the container
unsigned int capacity{ InitialCapacity }; // Current maximum capacity of the container
public:
// Construction and Destruction ---------------------------------------------------------------
DynamicArray(); // Default constructor. Allocate new memory
DynamicArray(const unsigned int size); // Constructor for a given size. Allocate new memory
DynamicArray(const DynamicArray& other); // Copy constructor. Make a deep copy
DynamicArray(DynamicArray&& other); // Move constructor
// Special constructors
template <class Iterator> DynamicArray(Iterator begin, Iterator end); // Initialize from range
template <int N> DynamicArray(const T(&other)[N]); // Initialize from C_Sytle array,e.g. a string literal
template <int N> DynamicArray(T(&other)[N]);
DynamicArray(const std::initializer_list<T>& list); // Take data from initializer list
~DynamicArray(); // Destructor: Release previously allocated memory
// Housekeeping ---------------------------------------------------------------
bool empty() const; // Do we have elements in the container? Do not mix up with capacity
void clear(); // Clear will not delete anything. Just set element count to 0
unsigned int size() const; // How many elements are in the container
// Main working functions
void push_back(const T& d); // Add a new element at the end
// Operators for class------------------------ ---------------------------------------------------------------
T operator[] (const unsigned int i) const; // Index operator, get data at given index. No boundary check
T& operator[] (const unsigned int i); // Index operator, get data at given index. No boundary check
DynamicArray& operator=(const DynamicArray& other); // Assignment
DynamicArray& operator=(DynamicArray&& other); // Move Assignment
// Add iterator properties to class ---------------------------------------------------------------
class iterator { // Local class for iterator
T* iter{}; // This will be the iterator
T* begin{}; // For boundary check
T* end{}; // For boundary check
public: // Define alias names necessary for the iterator functionality
using iterator_category = std::random_access_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
// Constructor
iterator(T* const i, T* const b, T* const e);
// Dereferencing
reference operator *() const;
pointer operator ->() const;
// Aithmetic operations
iterator& operator ++();
iterator& operator --();
iterator operator ++(int);
iterator operator --(int);
iterator operator +(const difference_type& n) const;
iterator& operator +=(const difference_type& n);
iterator operator -(const difference_type& n) const;
iterator& operator -=(const difference_type& n);
// Comparison
bool operator != (const iterator& other) const;
bool operator == (const iterator& other) const;
bool operator < (const iterator& other) const;
bool operator > (const iterator& other) const;
bool operator <= (const iterator& other) const;
bool operator >= (const iterator& other) const;
// Reference and difference
reference operator[] (const difference_type& n);
difference_type operator-(const iterator& other) const;
};
// Begin and end function to initialize an iterator
iterator begin() const;
iterator end() const;
// Working functions dealing with iterators. More may be added
iterator erase(iterator pos);
};
// Default constructor. Allocate new memory
template <typename T>
inline DynamicArray<T>::DynamicArray() {
data = new T[capacity];
}
// Constructor for certain size. Allocate new memory
template <typename T>
inline DynamicArray<T>::DynamicArray(const unsigned int size) : data(new T[size]), numberOfElements(0), capacity(size) {
}
// Copy constructor
template <typename T>
DynamicArray<T>::DynamicArray(const DynamicArray& other) { // Copy constructor. Make a deep copy
capacity = numberOfElements = other.numberOfElements;
data = new T[capacity]; // Get memory, same size as other container
for (size_t k = 0; k < other.numberOfElements; ++k)
data[k] = other.data[k]; // Copy data
}
// Move constructor
template <typename T>
DynamicArray<T>::DynamicArray(DynamicArray&& other) {
data = other.data;
numberOfElements = other.numberOfElements;
capacity = other.capacity;
other.capacity = InitialCapacity;
other.numberOfElements = 0;
other.data = new T[capacity];;
}
// Range constructor
template <typename T>
template <class Iterator>
DynamicArray<T>::DynamicArray(Iterator begin, Iterator end) {
data = new T[capacity];
for (Iterator i = begin; i != end; ++i)
push_back(*i);
}
// Construct from a const C-Style Array, like for example "Hello"
template <typename T>
template <int N>
DynamicArray<T>::DynamicArray(const T(&other)[N]) {
capacity = numberOfElements = N;
data = new T[capacity]; // Get memory, same size as other container
for (size_t k = 0; k < N; ++k)
data[k] = other[k]; // Copy data
}
// Construct from a C-Style Array
template <typename T>
template <int N>
DynamicArray<T>::DynamicArray(T(&other)[N]) {
capacity = numberOfElements = N;
data = new T[capacity]; // Get memory, same size as other container
for (size_t k = 0; k < N; ++k)
data[k] = other[k]; // Copy data
}
// Construct from an initializer list
template <typename T>
DynamicArray<T>::DynamicArray(const std::initializer_list<T>& list) {
data = new T[capacity];
for (const T& t : list) push_back(t);
}
// Destructor will release the dynamic allocated memory
template <typename T>
inline DynamicArray<T>::~DynamicArray() {
delete[] data;
} // Destructor: Release previously allocated memory
// Some houskeeping functions
template <typename T>
inline bool DynamicArray<T>::empty() const {
return numberOfElements == 0;
}
template <typename T>
inline void DynamicArray<T>::clear() {
numberOfElements = 0;
}; // Clear will not delete anything. Just set element count to 0
template <typename T>
inline unsigned int DynamicArray<T>::size() const {
return numberOfElements;
} // How many elements are in the container
// Main workhorse for a dynamic array.
// Store element, and alwaysprovide enough memory
template <typename T>
void DynamicArray<T>::push_back(const T& d) { // Add a new element at the end
if (numberOfElements >= capacity) { // Check, if capacity of this dynamic array is big enough
capacity *= 2; // Obviously not, we will double the capacity
T* temp = new T[capacity]; // Allocate new and more memory
for (unsigned int k = 0; k < numberOfElements; ++k)
temp[k] = data[k]; // Copy data from old memory to new memory
delete[] data; // Release old memory
data = temp; // And assign newly allocated memory to old pointer
}
data[numberOfElements++] = d; // And finally, store the given data at the end of the container
}
// Operators for class ------------------------ ---------------------------------------------------------------
template <typename T>
inline typename T DynamicArray<T>::operator[] (const unsigned int i) const {
return data[i];
} // Index operator, get data at given index. No boundary check
template <typename T>
inline typename T& DynamicArray<T>::operator[] (const unsigned int i) {
return data[i];
} // Index operator, get data at given index. No boundary check
// Assignement operator. Make a deep copy
template <typename T>
DynamicArray<T>& DynamicArray<T>::operator=(const DynamicArray& other) {
if (this != &other) { // Prevent self-assignment
delete[] data; // Release any previosly existing memory
capacity = numberOfElements = other.numberOfElements;// Take over capacity and number of elements from other container
data = new T[capacity]; // Get new memory, depending on size of other
for (unsigned int k = 0; k < numberOfElements; ++k) // Copy other data
data[k] = other.data[k];
}
return *this;
}
template <typename T>
DynamicArray<T>& DynamicArray<T>::operator=(DynamicArray&& other) { // Move Assignment
if (this != &other) { // Prevent self-assignment
data = other.data;
numberOfElements = other.numberOfElements;
capacity = other.capacity;
other.capacity = InitialCapacity;
other.numberOfElements = 0;
other.data = new T[capacity];;
}
return *this;
}
// Implementation of iterator functions ---------------------------------------------------------------------
// COnstruction
template <typename T>
inline DynamicArray<T>::iterator::iterator(T* const i, T* const b, T* const e) : iter(i), begin(b), end(e) {
}; // Constructor for the iterator
// Dereferencing
template <typename T>
inline typename DynamicArray<T>::iterator::reference DynamicArray<T>::iterator::operator *() const {
return *iter;
}
template <typename T>
inline typename DynamicArray<T>::iterator::pointer DynamicArray<T>::iterator::operator ->() const {
return iter;
}
// Arithmetic operations
template <typename T>
inline typename DynamicArray<T>::iterator& DynamicArray<T>::iterator::operator ++() {
if (iter < end)
++iter;
return *this;
}
template <typename T>
inline typename DynamicArray<T>::iterator& DynamicArray<T>::iterator::operator --() {
if (iter > begin)
--iter;
return *this;
}
template <typename T>
typename DynamicArray<T>::iterator DynamicArray<T>::iterator::operator ++(int) {
DynamicArray<T>::iterator tmp = *this;
if (this->iter < end)
++(*this);
return tmp;
}
template <typename T>
typename DynamicArray<T>::iterator DynamicArray<T>::iterator::operator --(int) {
DynamicArray<T>::iterator tmp = *this;
if (this->iter > begin)
--(*this);
return tmp;
}
template <typename T>
typename DynamicArray<T>::iterator DynamicArray<T>::iterator::operator +(const DynamicArray<T>::iterator::difference_type& n) const {
DynamicArray<T>::iterator tmp = *this;
DynamicArray<T>::iterator::difference_type k{ n };
if (k > 0)
while (k--)
++tmp;
else
while (k++)
--tmp;
return tmp;
}
template <typename T>
typename DynamicArray<T>::iterator& DynamicArray<T>::iterator::operator +=(const DynamicArray<T>::iterator::difference_type& n) {
DynamicArray<T>::iterator::difference_type k{ n };
if (k > 0)
while (k--)
++* this;
else
while (k++)
--* this;
return *this;
}
template <typename T>
typename DynamicArray<T>::iterator DynamicArray<T>::iterator::operator- (const DynamicArray<T>::iterator::difference_type& n) const {
DynamicArray<T>::iterator tmp = *this;
DynamicArray<T>::iterator::difference_type k{ n };
if (k > 0)
while (k--)
--tmp;
else
while (k++)
++tmp;
return tmp;
}
template <typename T>
typename DynamicArray<T>::iterator& DynamicArray<T>::iterator::operator -=(const typename DynamicArray<T>::iterator::difference_type& n) {
DynamicArray<T>::iterator::difference_type k{ n };
if (k > 0)
while (k--)
--* this;
else
while (k++)
++* this;
return *this;
}
// Comparison functions
template <typename T>
inline typename DynamicArray<T>::iterator::reference DynamicArray<T>::iterator::operator[] (const typename DynamicArray<T>::iterator::difference_type& n) {
return *(iter + n);
};
template <typename T>
inline bool DynamicArray<T>::iterator::operator != (const iterator& other) const {
return iter != other.iter;
}
template <typename T>
inline bool DynamicArray<T>::iterator::operator == (const iterator& other) const {
return iter == other.iter;
}
template <typename T>
inline bool DynamicArray<T>::iterator::operator < (const iterator& other) const {
return iter < other.iter;
}
template <typename T>
inline bool DynamicArray<T>::iterator::operator > (const iterator& other) const {
return iter > other.iter;
} // Comparison
template <typename T>
inline bool DynamicArray<T>::iterator::operator <= (const iterator& other) const {
return iter <= other.iter;
} // Comparison
template <typename T>
inline bool DynamicArray<T>::iterator::operator >= (const iterator& other) const {
return iter >= other.iter;
} // Comparison
// Delta
template <typename T>
inline typename DynamicArray<T>::iterator::difference_type DynamicArray<T>::iterator::operator-(const typename DynamicArray<T>::iterator& other) const {
return iter - other.iter;
}
// ------------------------------------------------------------------------
// Get iterators for dynamic array
template <typename T>
inline typename DynamicArray<T>::iterator DynamicArray<T>::begin() const {
return iterator(data, data, data + numberOfElements);
}
template <typename T>
inline typename DynamicArray<T>::iterator DynamicArray<T>::end() const {
return iterator(data + numberOfElements, data, data + numberOfElements);
}
// ------------------------------------------------------------------------
// Any other functions for dynamic array
template <typename T>
typename DynamicArray<T>::iterator DynamicArray<T>::erase(typename DynamicArray<T>::iterator pos) {
iterator result{ pos };
if (pos != end()) {
while (pos != end()) {
*pos = *(pos + 1);
++pos;
}
++result;
--numberOfElements;
}
return result;
}
// --------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// Using the dynamic array as a String, by using char as the content
using String = DynamicArray<char>;
// Some overloads for operators for easier handling
std::istream& operator >> (std::istream& is, String& s) {
s.clear();
char c{};
is >> std::ws;
while (is.peek() != EOF and is.get(c) and not isspace(c)) {
s.push_back(c);
}
if (not s.empty()) s.push_back(0);
return is;
}
std::ostream& operator << (std::ostream& os, const String& s) {
std::ostringstream oss;
for (char c : s) if (c != '\0') oss << c;
return os << oss.str();
}
bool operator < (const String& s1, const String& s2) {
unsigned int length{ (s1.size() < s2.size()) ? s1.size() : s2.size() };
for (unsigned int k{}; k < length; ++k) {
if (s1[k] == s2[k]) continue;
if (s1[k] < s2[k]) return true;
return false;
}
return false;
}
bool operator == (const String& s1, const String& s2) {
if (s1.size() != s2.size()) return false;
for (unsigned int k{}; k < s1.size(); ++k) {
if (s1[k] != s2[k]) return false;
}
return true;
}
bool operator != (const String& s1, const String& s2) { return not (s1 == s2); }
// --------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// Definition of a Hash Map (Like a std::unordered_map)
// Key and Value
struct Item {
String key{};
unsigned int count{};
};
// An entry in one bucket of the hash map will be a dynamic array for key/value pairs
using Entry = DynamicArray<Item>;
class HashMap {
// Some fixed default number for buckets
static constexpr unsigned int NumberOfBuckets = 4096;
Entry* buckets{}; // Buckets will be created dyanmically.
unsigned int numberOfElements{}; // NUmber of real elements in hash map
// Claculate the hash value. Maybe you find a better implementation
unsigned int getHash(const String& s) const;
public:
// Constructor and destructor
HashMap();
~HashMap();
// Houskeeping functions
unsigned int size() const;
bool empty() const;
bool contains(const String& s) const;
// 2 main functions for inserting and/or retrieving Pairs / avlues
Item& insert(const String& s);
unsigned int& operator[](const String& s);
// Add iterator properties to class ---------------------------------------------------------------
// Local class for iterator
class iterator {
int iterBucket{}; // Current position of the bucket
int iterEntry{}; // Current index in the dynamic array in the bucket
Entry* buckets; // Reference to buckets of the upper hash map
void next(); // Get the next entry in the hash map that contains a value
void previous(); // Get the previous entry in the hash map that contains a value
public: // Define alias names necessary for the iterator functionality
using iterator_category = std::random_access_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = Item;
using pointer = Item*;
// Please note: Making this const, will prevent that function like sort can be used.
// This operation would note make sense, or even destroy the hash map
using reference = const Item&;
// Constructor
iterator(Entry* const b, const unsigned int start);
// Dereferencing
reference operator *() const;
pointer operator ->() const;
// Arithmetic operations
iterator& operator ++();
iterator& operator --();
iterator operator ++(int);
iterator operator --(int);
iterator operator +(const difference_type& n) const;
iterator& operator +=(const difference_type& n);
iterator operator -(const difference_type& n) const;
iterator& operator -=(const difference_type& n);
// Comparison
bool operator == (const iterator& other) const;
bool operator != (const iterator& other) const;
bool operator < (const iterator& other) const;
bool operator > (const iterator& other) const;
bool operator <= (const iterator& other) const;
bool operator >= (const iterator& other) const;
// Get current indices
int getBucket() const;
int getEntry() const;
// Difference between 2 iterators. Not that simple in a hash map
difference_type operator-(const iterator& other) const;
};
// Begin and end function to initiliaze an iterator
iterator begin() const;
iterator end() const;
// Additional functions for working with a hash map
iterator find(const String& key);
iterator erase(iterator pos);
};
// ---------------------------------------------------------------------------------------------------------
// Construction and destruction
inline HashMap::HashMap() {
buckets = new Entry[NumberOfBuckets];
}
inline HashMap::~HashMap() {
delete[]buckets;
}
// Main hashing function. Find a good one. Has a major impact on number of collisions
inline unsigned int HashMap::getHash(const String& s) const {
unsigned long result = 5381;
for (char c : s) result = ((result << 5) + result) + c;
return result % NumberOfBuckets;
}
// Housekeeping
inline unsigned int HashMap::size() const {
return numberOfElements;
}
inline bool HashMap::empty() const {
return numberOfElements == 0;
}
inline bool HashMap::contains(const String& s) const {
for (Item& i : buckets[getHash(s)])
if (i.key == s) return true;
return false;;
}
// Main functions to deal with a hash map
Item& HashMap::insert(const String& s) {
unsigned int hash = getHash(s);
for (Item& i : buckets[hash]) {
if (i.key == s)
return i;
std::cout << "Collision\n";
}
buckets[hash].push_back({ s,0 });
++numberOfElements;
return buckets[hash][buckets[hash].size() - 1];
}
inline unsigned int& HashMap::operator[](const String& s) {
return insert(s).count;
}
// ---------------------------------------------------------------------------------------------------------
// Iterator for hash map
// Constructor
HashMap::iterator::iterator(Entry* const b, const unsigned int start) : iterBucket(start), iterEntry(0), buckets(b) {
for (; iterBucket < NumberOfBuckets; ++iterBucket)
if (buckets[iterBucket].size()) return;
};
// Navigation
void HashMap::iterator::next() {
const int s = buckets[iterBucket].size();
if ((s > 0) and (iterEntry < (s - 1)))
++iterEntry;
else {
iterEntry = 0;
if (iterBucket < NumberOfBuckets) ++iterBucket;
while ((iterBucket < NumberOfBuckets) and (buckets[iterBucket].size() == 0))
++iterBucket;
}
}
void HashMap::iterator::previous() {
if (iterEntry > 0)
--iterEntry;
else {
if (iterBucket > 0) --iterBucket;
while ((iterBucket > 0) and (buckets[iterBucket].size() == 0))
--iterBucket;
if (buckets[iterBucket].size() > 0)
iterEntry = buckets[iterBucket].size() - 1;
}
}
// Dereferencing
inline HashMap::iterator::reference HashMap::iterator::operator *() const {
return buckets[iterBucket][iterEntry];
}
inline HashMap::iterator::pointer HashMap::iterator::operator ->() const {
return &buckets[iterBucket][iterEntry];
}
// Arithmetic operations
inline HashMap::iterator& HashMap::iterator::operator ++() {
next();
return *this;
}
inline HashMap::iterator& HashMap::iterator::operator --() {
previous();
return *this;
}
inline HashMap::iterator HashMap::iterator::operator ++(int) {
iterator tmp = *this;
this->next();
return tmp;
}
inline HashMap::iterator HashMap::iterator::operator --(int) {
iterator tmp = *this;
this->previous();
return tmp;
}
HashMap::iterator HashMap::iterator::operator +(const HashMap::iterator::difference_type& n) const {
iterator tmp = *this;
difference_type k{ n };
if (k > 0)
while (k--)
tmp.next();
else
while (k++)
tmp.previous();
return tmp;
};
HashMap::iterator& HashMap::iterator::operator +=(const HashMap::iterator::difference_type& n) {
difference_type k{ n };
if (k > 0)
while (k--)
next();
else
while (k++)
previous();
return *this;
}
HashMap::iterator HashMap::iterator::operator -(const HashMap::iterator::difference_type& n) const {
iterator tmp = *this;
difference_type k{ n };
if (k > 0)
while (k--)
tmp.previous();
else
while (k++)
tmp.next();
return tmp;
};
HashMap::iterator& HashMap::iterator::operator -=(const HashMap::iterator::difference_type& n) {
difference_type k{ n };
if (k > 0)
while (k--)
previous();
else
while (k++)
next();
return *this;
}
// Comparison
inline bool HashMap::iterator::operator == (const iterator& other) const {
return iterBucket == other.iterBucket and iterEntry == other.iterEntry;
}
inline bool HashMap::iterator::operator != (const iterator& other) const {
return not (*this == other);
}
inline bool HashMap::iterator::operator < (const iterator& other) const {
return (iterBucket == other.iterBucket) ? (iterEntry < other.iterEntry) : (iterBucket < other.iterBucket);
}
inline bool HashMap::iterator::operator > (const iterator& other) const {
return (iterBucket == other.iterBucket) ? (iterEntry > other.iterEntry) : (iterBucket > other.iterBucket);
}
inline bool HashMap::iterator::operator <= (const iterator& other) const {
return *this == other or *this < other;
}
inline bool HashMap::iterator::operator >= (const iterator& other) const {
return *this == other or *this > other;
}
// Access to iterator internals
inline int HashMap::iterator::getBucket() const {
return iterBucket;
}
inline int HashMap::iterator::getEntry() const {
return iterEntry;
}
// Difference
inline HashMap::iterator::difference_type HashMap::iterator::operator-(const HashMap::iterator& other) const {
difference_type delta{};
iterator o = other;
while (o < *this) {
++delta;
++o;
}
return delta;
}
// -----------------------------------------------------------------------------------
// Back to hash map functions
HashMap::iterator HashMap::begin() const {
return iterator(buckets, 0);
}
HashMap::iterator HashMap::end() const {
return iterator(buckets, NumberOfBuckets);
}
// You may want to add additional functions here
HashMap::iterator HashMap::find(const String& key) {
iterator iter = begin();
for (; iter != end(); ++iter) {
if (iter->key == key)
return iter;
}
return iter;
}
HashMap::iterator HashMap::erase(HashMap::iterator pos) {
iterator result{ pos };
if (pos != end()) {
Entry::iterator i = buckets[pos.getBucket()].begin() + pos.getEntry();
buckets[pos.getBucket()].erase(i);
++result;
--numberOfElements;
}
return result;
}
// ---------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------
int main() {
// Create a dynamic hash map
HashMap hm{};
hm["English"] = 3;
hm["Math"] = 4;
// SHow resulton screen
for (const auto& [string, number] : hm)
std::cout << string << '\t' << number << '\n';
}