Skip to content

Instantly share code, notes, and snippets.

@mtimkovich
Last active July 2, 2017 23:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mtimkovich/9e12fd5f387dad473be64eea982ba874 to your computer and use it in GitHub Desktop.
Save mtimkovich/9e12fd5f387dad473be64eea982ba874 to your computer and use it in GitHub Desktop.
Remaking hash tables
#include <iostream>
#include <vector>
template <class K, class V>
class HashMap;
template <class K, class V>
class Entry {
K const key;
V value;
Entry<K, V> *next;
friend class HashMap<K, V>;
public:
Entry() : next(nullptr) {};
Entry(K k, V v) : key(k), value(v), next(nullptr) {}
int add(Entry<K, V> *e) {
if (next == nullptr) {
next = e;
return 1;
} else {
if (key == e->key) {
value = e->value;
delete e;
} else {
return next->add(e);
}
}
return 0;
}
int add(K key, V value) {
if (next == nullptr) {
next = new Entry<K, V>(key, value);
return 1;
} else {
if (this->key == key) {
this->value = value;
} else {
return next->add(key, value);
}
}
return 0;
}
Entry<K, V> *find(K key) {
Entry<K, V> *e = this;
for (; e != nullptr && e->key != key; e = e->next) {}
return e;
}
};
template <class K, class V>
class HashMap {
std::vector<Entry<K, V>*> table;
int elements;
int capacity;
int indexFor(K key, int cap) {
auto hashcode = std::hash<K>()(key);
return hashcode % cap;
}
int indexFor(K key) {
return indexFor(key, capacity);
}
public:
HashMap(int cap=16) : table(cap) {
capacity = cap;
elements = 0;
}
~HashMap() {
clear();
}
V put(K key, V value) {
int index = indexFor(key);
Entry<K, V> *prev = table[index];
if (prev == nullptr || key == prev->key) {
table[index] = new Entry<K, V>(key, value);
elements++;
} else {
elements += table[index]->add(key, value);
}
if (elements > capacity * .75) {
resize(capacity * 2);
}
return prev == nullptr ? V() : prev->value;
}
V &get(K key) {
if (!hasKey(key)) {
put(key, V());
}
int index = indexFor(key);
Entry<K, V> *e = table[index]->find(key);
return e->value;
}
V &operator[](K key) {
return get(key);
}
int size() {
return elements;
}
bool hasKey(K key) {
int index = indexFor(key);
Entry<K, V> *e = table[index];
return e->find(key) != nullptr;
}
bool isEmpty() {
return size() == 0;
}
V remove(K key) {
int index = indexFor(key);
Entry<K, V> *e = table[index];
Entry<K, V> *prev;
V prev_val;
if (e == nullptr) {
return V();
} else if (e->key == key) {
prev_val = e->value;
table[index] = e->next;
delete e;
elements--;
} else {
for (prev = e; e != nullptr && e->key != key; prev = e, e = e->next) {}
if (prev == nullptr || e == nullptr) {
return V();
}
prev->next = e->next;
prev_val = e->value;
delete e;
elements--;
}
return prev_val;
}
void clear() {
for (auto e : table) {
while (e != nullptr) {
auto next = e->next;
delete e;
e = next;
}
}
elements = 0;
}
void resize(int newCapacity) {
std::vector<Entry<K, V>*> newTable(capacity);
for (auto e : table) {
while (e != nullptr) {
auto next = e->next;
e->next = nullptr;
int i = indexFor(e->key, newCapacity);
if (newTable[i] == nullptr) {
newTable[i] = e;
} else {
newTable[i]->add(e);
}
e = next;
}
}
table = newTable;
capacity = newCapacity;
}
};
int main() {
HashMap<int, std::string> hash(4);
hash[0] = "zero";
hash[16] = "sixteen";
hash[32] = "thirty-two";
hash[1] = "one";
std::cout << hash[40] << std::endl;
std::cout << hash.hasKey(40) << std::endl;
std::cout << hash.hasKey(16) << std::endl;
std::cout << hash[16] << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment