HashMap.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #ifndef HASHMAP_H
  2. #define HASHMAP_H
  3. #include <iostream>
  4. #include "utils/Array.h"
  5. template<typename K, typename V, int N_MIN>
  6. class HashMap final {
  7. static constexpr int getCapacity() {
  8. int i = 1;
  9. while(i < N_MIN) {
  10. i <<= 1;
  11. }
  12. return i;
  13. }
  14. static constexpr int CAPACITY = getCapacity();
  15. static constexpr int MASK = CAPACITY - 1;
  16. Array<bool, CAPACITY> used;
  17. char keys[sizeof (K) * CAPACITY];
  18. char values[sizeof (V) * CAPACITY];
  19. const K& getKey(int index) const {
  20. return reinterpret_cast<const K*> (keys)[index];
  21. }
  22. V& getValue(int index) {
  23. return reinterpret_cast<V*> (values)[index];
  24. }
  25. const V& getValue(int index) const {
  26. return reinterpret_cast<const V*> (values)[index];
  27. }
  28. int searchIndex(const K& key) const {
  29. int base = hash(key);
  30. for(int i = 0; i < CAPACITY; i++) {
  31. int h = (base + i) & MASK;
  32. if(!used[h]) {
  33. return -h;
  34. } else if(getKey(h) == key) {
  35. return h;
  36. }
  37. }
  38. return -CAPACITY;
  39. }
  40. void copy(const HashMap& other) {
  41. for(int i = 0; i < other.CAPACITY; i++) {
  42. if(other.used[i]) {
  43. used[i] = true;
  44. new (reinterpret_cast<K*> (keys) + i) K(other.getKey(i));
  45. new (reinterpret_cast<V*> (values) + i) V(other.getValue(i));
  46. }
  47. }
  48. }
  49. void move(HashMap& other) {
  50. for(int i = 0; i < other.CAPACITY; i++) {
  51. if(other.used[i]) {
  52. used[i] = true;
  53. new (reinterpret_cast<K*> (keys) + i) K(std::move(other.getKey(i)));
  54. new (reinterpret_cast<V*> (values) + i) V(std::move(other.getValue(i)));
  55. }
  56. }
  57. other.clear();
  58. }
  59. public:
  60. HashMap() : used(false) {
  61. }
  62. ~HashMap() {
  63. clear();
  64. }
  65. HashMap(const HashMap& other) : used(false) {
  66. copy(other);
  67. }
  68. HashMap& operator=(const HashMap& other) {
  69. clear();
  70. copy(other);
  71. return *this;
  72. }
  73. HashMap(HashMap&& other) : used(false) {
  74. move(other);
  75. }
  76. HashMap& operator=(HashMap&& other) {
  77. clear();
  78. move(other);
  79. return *this;
  80. }
  81. void add(const K& key, const V& value) {
  82. int index = searchIndex(key);
  83. if(index >= 0) {
  84. getValue(index) = value;
  85. } else if(index > -CAPACITY) {
  86. index = -index;
  87. used[index] = true;
  88. new (reinterpret_cast<K*> (keys) + index) K(key);
  89. new (reinterpret_cast<V*> (values) + index) V(value);
  90. }
  91. }
  92. void add(const K& key, const V&& value) {
  93. int index = searchIndex(key);
  94. if(index >= 0) {
  95. getValue(index) = std::move(value);
  96. } else if(index > -CAPACITY) {
  97. index = -index;
  98. used[index] = true;
  99. new (reinterpret_cast<K*> (keys) + index) K(key);
  100. new (reinterpret_cast<V*> (values) + index) V(std::move(value));
  101. }
  102. }
  103. const V& search(const K& key, const V& notFound) const {
  104. int index = searchIndex(key);
  105. return index < 0 ? notFound : getValue(index);
  106. }
  107. V& search(const K& key, V& notFound) {
  108. int index = searchIndex(key);
  109. return index < 0 ? notFound : getValue(index);
  110. }
  111. bool contains(const K& key) const {
  112. return searchIndex(key) >= 0;
  113. }
  114. void clear() {
  115. K* k = reinterpret_cast<K*> (keys);
  116. V* v = reinterpret_cast<V*> (values);
  117. for(int i = 0; i < CAPACITY; i++) {
  118. if(used[i]) {
  119. k[i].~K();
  120. v[i].~V();
  121. }
  122. }
  123. used.fill(false);
  124. }
  125. private:
  126. template<typename H>
  127. static int hash(const H& key) {
  128. return key.hashCode();
  129. }
  130. static int hash(int key) {
  131. return key;
  132. }
  133. };
  134. #endif