Advertisement
Guest User

Untitled

a guest
Aug 20th, 2019
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.01 KB | None | 0 0
  1. #include <iostream>
  2.  
  3. template <typename K, typename V>
  4. class ExtendibleHash {
  5. public:
  6. // constructor
  7. ExtendibleHash(size_t size);
  8. // helper function to generate hash addressing
  9. size_t HashKey(const K &key);
  10. // helper function to get global & local depth
  11. int GetGlobalDepth() const;
  12. int GetLocalDepth(int bucket_id) const;
  13. int GetNumBuckets() const;
  14. // lookup and modifier
  15. bool Find(const K &key, V &value);
  16. bool Remove(const K &key);
  17. void Insert(const K &key, const V &value);
  18.  
  19. // add your own member variables here
  20. int size; // size of each bucket: how many records
  21. int num; // total number of buckets
  22. int globalDepth;
  23.  
  24. struct Record
  25. {
  26. K *kptr;
  27. V *vptr;
  28. };
  29.  
  30. struct Bucket
  31. {
  32. int localDepth;
  33. int counter;
  34. Record *recordArray;
  35. };
  36.  
  37. Bucket **addressTable; // address table to link to all buckets
  38. };
  39.  
  40. template <typename K, typename V>
  41. ExtendibleHash<K, V>::ExtendibleHash(size_t _size) {
  42. size = _size;
  43.  
  44. // initialize address table with depth 1
  45. globalDepth = 1;
  46. num = 2;
  47. addressTable = (Bucket **)malloc(2 * sizeof(Bucket *));
  48. for (int i = 0; i < num; ++i)
  49. {
  50. Bucket *b = (Bucket *)malloc(sizeof(Bucket));
  51. b->localDepth = 1;
  52. b->counter = 0;
  53. b->recordArray = (Record *)malloc(size * sizeof(Record));
  54. addressTable[i] = b;
  55. }
  56. }
  57.  
  58. /*
  59. * helper function to calculate the hashing address of input key
  60. */
  61. template <typename K, typename V>
  62. size_t ExtendibleHash<K, V>::HashKey(const K &key) {
  63. int m = ~(0xffffffff << globalDepth); // mask the bits
  64. long v = 0, b = 1, p = 1000000007; // to calculate polynomial
  65. uintptr_t a = (uintptr_t)(&key); // address[0] for key object
  66. int size = sizeof(K); // byte size of key
  67.  
  68. // iterate over all bytes of K
  69. for (int i = 0; i < size; ++i)
  70. {
  71. // when one pointer moves 1 step(+1)
  72. // the corresponding bits moves 1 char(8bit)
  73. unsigned char t = *(reinterpret_cast<unsigned char*>(i + a));
  74. v = ((t * b) % p + v) % p;
  75. b = (b * 31) % p;
  76. }
  77. return (size_t)v & m;
  78. }
  79.  
  80. /*
  81. * helper function to return global depth of hash table
  82. * NOTE: you must implement this function in order to pass test
  83. */
  84. template <typename K, typename V>
  85. int ExtendibleHash<K, V>::GetGlobalDepth() const {
  86. return globalDepth;
  87. }
  88.  
  89. /*
  90. * helper function to return local depth of one specific bucket
  91. * NOTE: you must implement this function in order to pass test
  92. */
  93. template <typename K, typename V>
  94. int ExtendibleHash<K, V>::GetLocalDepth(int bucket_id) const {
  95. return addressTable[bucket_id]->localDepth;
  96. }
  97.  
  98. /*
  99. * helper function to return current number of bucket in hash table
  100. */
  101. template <typename K, typename V>
  102. int ExtendibleHash<K, V>::GetNumBuckets() const {
  103. return num;
  104. }
  105.  
  106. /*
  107. * lookup function to find value associate with input key
  108. */
  109. template <typename K, typename V>
  110. bool ExtendibleHash<K, V>::Find(const K &key, V &value) {
  111. return false;
  112. }
  113.  
  114. /*
  115. * delete <key,value> entry in hash table
  116. * Shrink & Combination is not required for this project
  117. */
  118. template <typename K, typename V>
  119. bool ExtendibleHash<K, V>::Remove(const K &key) {
  120. return false;
  121. }
  122.  
  123. /*
  124. * insert <key,value> entry in hash table
  125. * Split & Redistribute bucket when there is overflow and if necessary increase
  126. * global depth
  127. */
  128. template <typename K, typename V>
  129. void ExtendibleHash<K, V>::Insert(const K &key, const V &value) {
  130. size_t hid = HashKey(key);
  131.  
  132. // bucket to be inserted
  133. Bucket *b = addressTable[hid];
  134.  
  135. if (b->counter < size)
  136. {
  137. // inserting without splitting
  138. b->recordArray[b->counter].kptr = (K *)&key;
  139. b->recordArray[b->counter].vptr = (V *)&value;
  140. b->counter += 1;
  141. }
  142. else
  143. {
  144. int _globalDepth = globalDepth;
  145. int _localDepth = b->localDepth;
  146.  
  147. if (_localDepth + 1 > _globalDepth)
  148. {
  149. // expend and update addressTable
  150. globalDepth = globalDepth + 1;
  151. Bucket **_addressTable = (Bucket **)malloc((1 << globalDepth) * sizeof(Bucket *));
  152.  
  153. // copy the original addressTable
  154. for (int i = 0; i < (1 << _globalDepth); ++i)
  155. {
  156. _addressTable[i] = addressTable[i];
  157. _addressTable[i | (1 << _globalDepth)] = addressTable[i];
  158. }
  159.  
  160. // update pointer
  161. Bucket **p = addressTable;
  162. addressTable = _addressTable;
  163. free(p);
  164. }
  165. // else, do not update addressTable
  166.  
  167. // splitting without expending
  168. // initialization
  169. Bucket *b0 = (Bucket *)malloc(sizeof(Bucket));
  170. b0->localDepth = _localDepth + 1;
  171. b0->counter = 0;
  172. b0->recordArray = (Record *)malloc(size * sizeof(Record));
  173.  
  174. Bucket *b1 = (Bucket *)malloc(sizeof(Bucket));
  175. b1->counter = 0;
  176. b1->localDepth = _localDepth + 1;
  177. b1->recordArray = (Record *)malloc(size * sizeof(Record));
  178.  
  179. // hashkey has been updated since globalDepth IS updated
  180. if (((HashKey(key) >> _localDepth) & 0x1) == 0)
  181. {
  182. b0->recordArray[b0->counter].kptr = (K *)&key;
  183. b0->recordArray[b0->counter].vptr = (V *)&value;
  184. b0->counter++;
  185. }
  186. else
  187. {
  188. b1->recordArray[b1->counter].kptr = (K *)&key;
  189. b1->recordArray[b1->counter].vptr = (V *)&value;
  190. b1->counter++;
  191. }
  192.  
  193. // split bucket b
  194. for (int i = 0; i < size; ++i)
  195. {
  196. K _key = *(b->recordArray[i].kptr);
  197. if (((HashKey(_key) >> _localDepth) & 0x1) == 0)
  198. {
  199. b0->recordArray[b0->counter].kptr = b->recordArray[i].kptr;
  200. b0->recordArray[b0->counter].vptr = b->recordArray[i].vptr;
  201. b0->counter++;
  202. }
  203. else
  204. {
  205. b1->recordArray[b1->counter].kptr = b->recordArray[i].kptr;
  206. b1->recordArray[b1->counter].vptr = b->recordArray[i].vptr;
  207. b1->counter++;
  208. }
  209. }
  210.  
  211. // update
  212. num++;
  213. free(b->recordArray);
  214. free(addressTable[hid]); // delete b
  215.  
  216. int _hid = hid ^ (1 << _localDepth);
  217. if (((hid >> _localDepth) & 0x1) == 0)
  218. {
  219. addressTable[hid] = b0;
  220. addressTable[_hid] = b1;
  221. }
  222. else
  223. {
  224. addressTable[hid] = b1;
  225. addressTable[_hid] = b0;
  226. }
  227. }
  228. }
  229.  
  230. template class ExtendibleHash<int, std::string>;
  231. template class ExtendibleHash<int, int>;
  232.  
  233. int main()
  234. {
  235. ExtendibleHash<int, std::string> *test =
  236. new ExtendibleHash<int, std::string>(2);
  237.  
  238. // insert several key/value pairs
  239. test->Insert(1, "a");
  240. test->Insert(2, "b");
  241. test->Insert(3, "c");
  242. test->Insert(4, "d");
  243. test->Insert(5, "e");
  244. test->Insert(6, "f");
  245. test->Insert(7, "g");
  246. test->Insert(8, "h");
  247. test->Insert(9, "i");
  248. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement