#ifndef _HASH_CC #define _HASH_CC #include #include "Hash.h" #include "AssocList.cc" #include "test_utilities.h" // destructor template HashTable::~HashTable() {} // constructor without default value template HashTable::HashTable() : starting_modulus(7), n_keys(0), hash_modulus(starting_modulus), use_default(0) { } // constructor with default value template HashTable::HashTable(VALUE const &def) : starting_modulus(7), n_keys(0), hash_modulus(starting_modulus), use_default(1), default_init(def) { } // copy constructor template HashTable::HashTable(const HashTable& a) : starting_modulus(a.starting_modulus), n_keys(a.n_keys), hash_modulus(a.hash_modulus), buckets(a.buckets) // calls copy constructor for Array > { } // operator= template // deep copy HashTable& HashTable::operator=(const HashTable& a) { n_keys = a.n_keys; hash_modulus = a.hash_modulus; buckets = a.buckets; // deep copy, okay if &a == this return *this; } // clear template void HashTable::clear() { n_keys = 0; hash_modulus = starting_modulus; buckets.clear(); } // hash template int HashTable::hash(KEY const & k) const { return Hash(k) % hash_modulus; } // grow template void HashTable::grow() { const int new_modulus = hash_modulus * 3; const Array _keys = keys(); const HashTable copy(*this); // only works if copy constructor cannot call grow clear(); hash_modulus = new_modulus; for (int i = 0; i < _keys.size(); ++i) (*this)[_keys[i]] = copy[_keys[i]]; } // exists template int HashTable::exists(KEY const & k) const { return hash(k) < buckets.size() && buckets[hash(k)].exists(k); } // remove template void HashTable::remove(KEY const & k) { if (exists(k)) --n_keys; buckets[hash(k)].remove(k); } // operator[] and const operator[] template VALUE & HashTable::operator[](KEY const & k) { if (n_keys >= hash_modulus) grow(); if (! exists(k)) { ++n_keys; if (use_default) buckets[hash(k)][k] = default_init; } return buckets[hash(k)][k]; } template VALUE HashTable::operator[](KEY const & k) const { if (exists(k)) return buckets[hash(k)][k]; die("HashTable index out of range"); } // keys() and values() template Array HashTable::keys() const { Array keys; for (int i = 0; i < buckets.size(); ++i) { Array bucket_keys = buckets[i].keys(); for (int j = 0; j < bucket_keys.size(); ++j) keys[keys.size()] = bucket_keys[j]; } return keys; } template Array HashTable::values() const { Array values; for (int i = 0; i < buckets.size(); ++i) { Array bucket_values = buckets[i].values(); for (int j = 0; j < bucket_values.size(); ++j) values[values.size()] = bucket_values[j]; } return values; } // operator<< template std::ostream & operator<<(std::ostream & out, const HashTable & a) { out << "n_keys = " << a.n_keys << ", hash_modulus = " << a.hash_modulus << "\nbuckets = {" << std::endl; for (int i = 0; i < a.buckets.size(); ++i) { if (i != 0) out << "," << std::endl; out << " bucket[" << i << "] = " << a.buckets[i]; } out << "\n}" << std::endl; return out; } #endif