X-Git-Url: http://plrg.eecs.uci.edu/git/?p=c11tester.git;a=blobdiff_plain;f=hashtable.h;h=b7cac67410c287004e9861d14db91c4afc0367dd;hp=16744bb45f39e89a165bf12a804c96cad466123b;hb=7742256df627848c1c375f979f5369a45c92057b;hpb=110873aa95a98a28561165f803d21a9b050205ed diff --git a/hashtable.h b/hashtable.h index 16744bb4..b7cac674 100644 --- a/hashtable.h +++ b/hashtable.h @@ -62,7 +62,7 @@ inline bool default_equals(_Key key1, _Key key2) { * @tparam _free Provide your own 'free' for the table, or default to * snapshotting. */ -template, bool (*equals)(_Key, _Key) = default_equals<_Key> > +template, bool (*equals)(_Key, _Key) = default_equals<_Key> > class HashTable { public: /** @@ -81,7 +81,7 @@ public: capacitymask = initialcapacity - 1; threshold = (unsigned int)(initialcapacity * loadfactor); - size = 0; // Initial number of elements in the hash + size = 0; // Initial number of elements in the hash } /** @brief Hash table destructor */ @@ -182,24 +182,38 @@ public: resize(capacity << 1); struct hashlistnode<_Key, _Val> *search; + struct hashlistnode<_Key, _Val> *first = NULL; - unsigned int index = hash_function(key); + unsigned int index = hash_function(key) & capacitymask; + unsigned int oindex = index; do { - index &= capacitymask; search = &table[index]; if (!search->key) { //key is null, probably done - break; + if (!search->val) + break; + if (first == NULL) + first = search; } if (equals(search->key, key)) { search->val = val; return; } - index++; + index = (index + 1) & capacitymask; + if (index == oindex) { + if (first == NULL) + exit(-1); + break; + } } while (true); - search->key = key; - search->val = val; + if (first != NULL) { + first->key = key; + first->val = val; + } else { + search->key = key; + search->val = val; + } size++; } @@ -220,7 +234,7 @@ public: } unsigned int oindex = hash_function(key) & capacitymask; - unsigned int index=oindex; + unsigned int index = oindex; do { search = &table[index]; if (!search->key) { @@ -244,6 +258,7 @@ public: */ _Val remove(_Key key) { struct hashlistnode<_Key, _Val> *search; + struct hashlistnode<_Key, _Val> *replace; /* HashTable cannot handle 0 as a key */ if (!key) { @@ -266,14 +281,40 @@ public: if (!search->key) { if (!search->val) break; - } else - if (equals(search->key, key)) { - _Val v=search->val; - //empty out this bin - search->val=(_Val) 1; - search->key=0; - size--; - return v; + } else { + // The case where an item is found + if (equals(search->key, key)) { + unsigned int j = index; + _Val v = search->val; + size--; + + // Idea: keep bins contiguous + while (true) { + search->val = 0; + search->key = 0; + + while (true) { + j = (j + 1) & capacitymask; + replace = &table[j]; + + if (!replace->key && !replace->val) { + return v; + } + + unsigned int hash = hash_function(replace->key) & capacitymask; + if (index <= j && index < hash && hash <= j) + continue; + else if (index > j && (index < hash || hash <= j) ) + continue; + else + break; + } + + table[index] = table[j]; + index = j; + search = &table[index]; + } + } } index++; } while (true); @@ -284,6 +325,9 @@ public: return size; } + bool isEmpty() { + return size == 0; + } /** * @brief Check whether the table contains a value for the given key @@ -327,7 +371,7 @@ public: exit(EXIT_FAILURE); } - table = newtable; // Update the global hashtable upon resize() + table = newtable; // Update the global hashtable upon resize() capacity = newsize; capacitymask = newsize - 1; @@ -353,7 +397,7 @@ public: search->val = bin->val; } - _free(oldtable); // Free the memory of the old hash table + _free(oldtable); // Free the memory of the old hash table } double getLoadFactor() {return loadfactor;} unsigned int getCapacity() {return capacity;} @@ -367,4 +411,4 @@ private: double loadfactor; }; -#endif/* __HASHTABLE_H__ */ +#endif /* __HASHTABLE_H__ */