#ifndef _hashmap_h
#define _hashmap_h
#include <cstdlib>
#include <string>
#include "vector.h"
int hashCode(const std::string & key);
int hashCode(int key);
int hashCode(char key);
int hashCode(long key);
int hashCode(double key);
template <typename KeyType, typename ValueType>
class HashMap {
public:
HashMap();
virtual ~HashMap();
int size() const;
bool isEmpty() const;
void put(KeyType key, ValueType value);
ValueType get(KeyType key) const;
bool containsKey(KeyType key) const;
void remove(KeyType key);
void clear();
ValueType & operator[](KeyType key);
ValueType operator[](KeyType key) const;
std::string toString();
void mapAll(void (*fn)(KeyType, ValueType)) const;
void mapAll(void (*fn)(const KeyType &, const ValueType &)) const;
template <typename FunctorType>
void mapAll(FunctorType fn) const;
private:
static const int INITIAL_BUCKET_COUNT = 101;
static const int MAX_LOAD_PERCENTAGE = 70;
struct Cell {
KeyType key;
ValueType value;
Cell *next;
};
Vector<Cell *> buckets;
int nBuckets;
int numEntries;
void createBuckets(int nBuckets) {
if (nBuckets == 0) nBuckets = 1;
buckets = Vector<Cell *>(nBuckets, NULL);
this->nBuckets = nBuckets;
numEntries = 0;
}
void deleteBuckets(Vector <Cell *> & buckets) {
for (int i = 0; i < buckets.size(); i++) {
Cell *cp = buckets[i];
while (cp != NULL) {
Cell *np = cp->next;
delete cp;
cp = np;
}
buckets[i] = NULL;
}
}
void expandAndRehash() {
Vector<Cell *>oldBuckets = buckets;
createBuckets(oldBuckets.size() * 2 + 1);
for (int i = 0; i < oldBuckets.size(); i++) {
for (Cell *cp = oldBuckets[i]; cp != NULL; cp = cp->next) {
put(cp->key, cp->value);
}
}
deleteBuckets(oldBuckets);
}
Cell *findCell(int bucket, KeyType key) const {
Cell *dummy;
return findCell(bucket, key, dummy);
}
Cell *findCell(int bucket, KeyType key, Cell * & parent) const {
parent = NULL;
Cell *cp = buckets.get(bucket);
while (cp != NULL && key != cp->key) {
parent = cp;
cp = cp->next;
}
return cp;
}
void deepCopy(const HashMap & src) {
createBuckets(src.nBuckets);
for (int i = 0; i < src.nBuckets; i++) {
for (Cell *cp = src.buckets.get(i); cp != NULL; cp = cp->next) {
put(cp->key, cp->value);
}
}
}
public:
HashMap & operator=(const HashMap & src) {
if (this != &src) {
clear();
deepCopy(src);
}
return *this;
}
HashMap(const HashMap & src) {
deepCopy(src);
}
class iterator : public std::iterator<std::input_iterator_tag,KeyType> {
private:
const HashMap *mp;
int bucket;
Cell *cp;
public:
iterator() {
}
iterator(const HashMap *mp, bool end) {
this->mp = mp;
if (end) {
bucket = mp->nBuckets;
cp = NULL;
} else {
bucket = 0;
cp = mp->buckets.get(bucket);
while (cp == NULL && ++bucket < mp->nBuckets) {
cp = mp->buckets.get(bucket);
}
}
}
iterator(const iterator & it) {
mp = it.mp;
bucket = it.bucket;
cp = it.cp;
}
iterator & operator++() {
cp = cp->next;
while (cp == NULL && ++bucket < mp->nBuckets) {
cp = mp->buckets.get(bucket);
}
return *this;
}
iterator operator++(int) {
iterator copy(*this);
operator++();
return copy;
}
bool operator==(const iterator & rhs) {
return mp == rhs.mp && bucket == rhs.bucket && cp == rhs.cp;
}
bool operator!=(const iterator & rhs) {
return !(*this == rhs);
}
KeyType operator*() {
return cp->key;
}
KeyType *operator->() {
return &cp->key;
}
friend class HashMap;
};
iterator begin() const {
return iterator(this, false);
}
iterator end() const {
return iterator(this, true);
}
};
template <typename KeyType,typename ValueType>
HashMap<KeyType,ValueType>::HashMap() {
createBuckets(INITIAL_BUCKET_COUNT);
}
template <typename KeyType,typename ValueType>
HashMap<KeyType,ValueType>::~HashMap() {
deleteBuckets(buckets);
}
template <typename KeyType,typename ValueType>
int HashMap<KeyType,ValueType>::size() const {
return numEntries;
}
template <typename KeyType,typename ValueType>
bool HashMap<KeyType,ValueType>::isEmpty() const {
return size() == 0;
}
template <typename KeyType,typename ValueType>
void HashMap<KeyType,ValueType>::put(KeyType key, ValueType value) {
(*this)[key] = value;
}
template <typename KeyType,typename ValueType>
ValueType HashMap<KeyType,ValueType>::get(KeyType key) const {
Cell *cp = findCell(hashCode(key) % nBuckets, key);
if (cp == NULL) return ValueType();
return cp->value;
}
template <typename KeyType,typename ValueType>
bool HashMap<KeyType,ValueType>::containsKey(KeyType key) const {
return findCell(hashCode(key) % nBuckets, key) != NULL;
}
template <typename KeyType,typename ValueType>
void HashMap<KeyType,ValueType>::remove(KeyType key) {
int bucket = hashCode(key) % nBuckets;
Cell *parent;
Cell *cp = findCell(bucket, key, parent);
if (cp != NULL) {
if (parent == NULL) {
buckets[bucket] = cp->next;
} else {
parent->next = cp->next;
}
delete cp;
numEntries--;
}
}
template <typename KeyType,typename ValueType>
void HashMap<KeyType,ValueType>::clear() {
deleteBuckets(buckets);
numEntries = 0;
}
template <typename KeyType,typename ValueType>
ValueType & HashMap<KeyType,ValueType>::operator[](KeyType key) {
int bucket = hashCode(key) % nBuckets;
Cell *cp = findCell(bucket, key);
if (cp == NULL) {
if (numEntries > MAX_LOAD_PERCENTAGE * nBuckets / 100.0) {
expandAndRehash();
bucket = hashCode(key) % nBuckets;
}
cp = new Cell;
cp->key = key;
cp->value = ValueType();
cp->next = buckets[bucket];
buckets[bucket] = cp;
numEntries++;
}
return cp->value;
}
template <typename KeyType,typename ValueType>
void HashMap<KeyType,ValueType>::mapAll(void (*fn)(KeyType, ValueType)) const {
for (int i = 0 ; i < buckets.size(); i++) {
for (Cell *cp = buckets.get(i); cp != NULL; cp = cp->next) {
fn(cp->key, cp->value);
}
}
}
template <typename KeyType,typename ValueType>
void HashMap<KeyType,ValueType>::mapAll(void (*fn)(const KeyType &,
const ValueType &)) const {
for (int i = 0 ; i < buckets.size(); i++) {
for (Cell *cp = buckets.get(i); cp != NULL; cp = cp->next) {
fn(cp->key, cp->value);
}
}
}
template <typename KeyType,typename ValueType>
template <typename FunctorType>
void HashMap<KeyType,ValueType>::mapAll(FunctorType fn) const {
for (int i = 0 ; i < buckets.size(); i++) {
for (Cell *cp = buckets.get(i); cp != NULL; cp = cp->next) {
fn(cp->key, cp->value);
}
}
}
template <typename KeyType, typename ValueType>
ValueType HashMap<KeyType,ValueType>::operator[](KeyType key) const {
return get(key);
}
template <typename KeyType, typename ValueType>
std::string HashMap<KeyType,ValueType>::toString() {
ostringstream os;
os << *this;
return os.str();
}
template <typename KeyType, typename ValueType>
std::ostream & operator<<(std::ostream & os,
const HashMap<KeyType,ValueType> & map) {
os << "{";
typename HashMap<KeyType,ValueType>::iterator begin = map.begin();
typename HashMap<KeyType,ValueType>::iterator end = map.end();
typename HashMap<KeyType,ValueType>::iterator it = begin;
while (it != end) {
if (it != begin) os << ", ";
writeGenericValue(os, *it, false);
os << ":";
writeGenericValue(os, map[*it], false);
++it;
}
return os << "}";
}
template <typename KeyType, typename ValueType>
std::istream & operator>>(std::istream & is,
HashMap<KeyType,ValueType> & map) {
char ch;
is >> ch;
if (ch != '{') error("operator >>: Missing {");
map.clear();
is >> ch;
if (ch != '}') {
is.unget();
while (true) {
KeyType key;
readGenericValue(is, key);
is >> ch;
if (ch != ':') error("operator >>: Missing colon after key");
ValueType value;
readGenericValue(is, value);
map[key] = value;
is >> ch;
if (ch == '}') break;
if (ch != ',') {
error(std::string("operator >>: Unexpected character ") + ch);
}
}
}
return is;
}
#endif