_Key key;
_Val val;
uint hashcode;
+ struct Hashlistnode<_Key, _Val> *next;
+ struct Hashlistnode<_Key, _Val> *prev;
};
template<typename _Key, int _Shift, typename _KeyInt>
* manipulation and storage.
* @tparam _Shift Logical shift to apply to all keys. Default 0.
*/
+
template<typename _Key, typename _Val, typename _KeyInt = uintptr_t, int _Shift = 0, unsigned int (*hash_function)(_Key) = defaultHashFunction<_Key, _Shift, _KeyInt>, bool (*equals)(_Key, _Key) = defaultEquals<_Key> >
class Hashtable {
public:
* @param factor Sets the percentage full before the hashtable is
* resized. Default ratio 0.5.
*/
- Hashtable(unsigned int initialcapacity = 1024, double factor = 0.5) {
+ Hashtable(unsigned int initialcapacity = 32, double factor = 0.5) {
// Allocate space for the hash table
table = (struct Hashlistnode<_Key, _Val> *)ourcalloc(initialcapacity, sizeof(struct Hashlistnode<_Key, _Val>));
zero = NULL;
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
+ tail = list = NULL;
+ }
+
+ Hashtable<_Key, _Val, _KeyInt, _Shift, hash_function, equals> *clone() {
+ Hashtable<_Key, _Val, _KeyInt, _Shift, hash_function, equals> *ctable = new Hashtable<_Key, _Val, _KeyInt, _Shift, hash_function, equals> (capacity, loadfactor);
+ struct Hashlistnode<_Key, _Val> *ptr = list;
+ while (ptr != NULL) {
+ ctable->put(ptr->key, ptr->val);
+ ptr = ptr->next;
+ }
+ return ctable;
}
+
/** @brief Hash table destructor */
~Hashtable() {
ourfree(table);
}
/** @brief Reset the table to its initial state. */
- void reset() {
+ void clear() {
memset(table, 0, capacity * sizeof(struct Hashlistnode<_Key, _Val>));
if (zero) {
ourfree(zero);
zero = NULL;
}
- size = 0;
+ Size = 0;
+ tail = list = NULL;
}
/** Doesn't work with zero value */
ourfree(zero);
zero = NULL;
}
- size = 0;
+ Size = 0;
+ tail = list = NULL;
}
void resetAndDeleteVals() {
ourfree(zero);
zero = NULL;
}
- size = 0;
+ Size = 0;
+ tail = list = NULL;
}
void resetAndFreeVals() {
ourfree(zero);
zero = NULL;
}
- size = 0;
+ Size = 0;
+ tail = list = NULL;
}
/**
* @param key The key for the new value; must not be 0 or NULL
* @param val The value to store in the table
*/
- void put(_Key key, _Val val) {
+ _Val put(_Key key, _Val val) {
/* Hashtable cannot handle 0 as a key */
if (!key) {
+ _Val oldval;
if (!zero) {
zero = (struct Hashlistnode<_Key, _Val> *)ourmalloc(sizeof(struct Hashlistnode<_Key, _Val>));
- size++;
- }
+ zero->next = list;
+ if (list != NULL)
+ list->prev = zero;
+ else
+ tail = zero;
+ list = zero;
+ Size++;
+ oldval = (_Val) 0;
+ } else
+ oldval = zero->val;
zero->key = key;
zero->val = val;
- return;
+ return oldval;
}
- if (size > threshold)
+ if (Size > threshold)
resize(capacity << 1);
struct Hashlistnode<_Key, _Val> *search;
}
if (search->hashcode == hashcode)
if (equals(search->key, key)) {
+ _Val oldval = search->val;
search->val = val;
- return;
+ return oldval;
}
index++;
} while (true);
search->key = key;
search->val = val;
search->hashcode = hashcode;
- size++;
+ search->next = list;
+ if (list == NULL)
+ tail = search;
+ else
+ list->prev = search;
+ list = search;
+ Size++;
+ return (_Val) 0;
}
/**
_Val remove(_Key key) {
struct Hashlistnode<_Key, _Val> *search;
- /* Hashtable cannot handle 0 as a key */
if (!key) {
if (!zero) {
return (_Val)0;
} else {
_Val v = zero->val;
+ if (zero->next != NULL)
+ zero->next->prev = zero->prev;
+ else
+ tail = zero->prev;
+
+ if (zero->prev != NULL)
+ zero->prev->next = zero->next;
+ else
+ list = zero->next;
+
ourfree(zero);
zero = NULL;
- size--;
+ Size--;
return v;
}
}
//empty out this bin
search->val = (_Val) 1;
search->key = 0;
- size--;
+
+ if (search->next != NULL)
+ search->next->prev = search->prev;
+ else
+ tail = search->prev;
+
+ if (search->prev != NULL)
+ search->prev->next = search->next;
+ else
+ list = search->next;
+
+ Size--;
return v;
}
index++;
return (_Val)0;
}
- unsigned int getSize() const {
- return size;
+ unsigned int size() const {
+ return Size;
}
table = newtable; // Update the global hashtable upon resize()
capacity = newsize;
capacitymask = newsize - 1;
-
+ list = tail = NULL;
threshold = (unsigned int)(newsize * loadfactor);
struct Hashlistnode<_Key, _Val> *bin = &oldtable[0];
index++;
} while (search->key);
+ if (tail == NULL)
+ tail = search;
+ search->next = list;
+ if (list != NULL)
+ list->prev = search;
+ list = search;
search->hashcode = hashcode;
search->key = key;
search->val = bin->val;
unsigned int getCapacity() {return capacity;}
struct Hashlistnode<_Key, _Val> *table;
struct Hashlistnode<_Key, _Val> *zero;
+ struct Hashlistnode<_Key, _Val> *list;
+ struct Hashlistnode<_Key, _Val> *tail;
unsigned int capacity;
- unsigned int size;
+ unsigned int Size;
private:
unsigned int capacitymask;
unsigned int threshold;