//====================================================================== // File: hash.h // Author: Timothy A. Budd // Description: This file contains the interface and implementation // of the hash template classes. // // Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. //====================================================================== #ifndef HASH_H #define HASH_H #include "iterator.h" #include "vector.h" #include "list.h" #include "tree.h" //---------------------------------------------------------------------- // class hashVector // vector indexed using hashed key values // template types are type of key // and type of value stored in vector //---------------------------------------------------------------------- template class hashVector : public vector { public: // constructors hashVector(int max, int (*f)(const H &)); hashVector(int max, int (*f)(const H &), T & initialValue); hashVector(const hashVector & v); // subscript operation T & operator [] (const H & idx); private: // store the hash function int (*hashfun)(const H &); }; //---------------------------------------------------------------------- // class hashTable // collection of buckets indexed by hashed values // template types // B - bucket type // H - key value // T - element held in buckets //---------------------------------------------------------------------- template class hashTableIterator; template class hashTable { public: // constructor hashTable(unsigned int max, unsigned int (*f)(const H &)); // test if the set is empty virtual int isEmpty(); // clear the elements of the set virtual void deleteAllValues(); protected: friend class hashTableIterator; // the actual table itself is a vector of buckets const unsigned int tablesize; vector buckets; unsigned int (*hashfun)(const H &); // convert key into unsigned integer value in range unsigned int hash(const H & key) const; // make iterator for given position in table virtual iterator * makeIterator(unsigned int) = 0; }; //---------------------------------------------------------------------- // class hashTree // hash table implemented using trees for buckets //---------------------------------------------------------------------- template class hashTree : public hashTable, T, T> { public: // constructor hashTree(unsigned int max, unsigned int (*f)(const T &)); // add an element to the collection void add(T newele); // test to see if the collect includes an element int includes(T ele) const; // remove an element void remove(T ele); protected: virtual iterator * makeIterator(unsigned int i); }; //---------------------------------------------------------------------- // class hashTableIterator // iterator protocol for hash tables //---------------------------------------------------------------------- template class hashTableIterator : public iterator { public: // constructor hashTableIterator(hashTable & v); // iterator protocol virtual int init(); virtual T operator()(); virtual int operator !(); virtual int operator ++(); virtual void operator =(T value); protected: hashTable & base; unsigned int currentIndex; iterator * itr; // getNextIterator used to set internal iterator pointer int getNextIterator(); }; //---------------------------------------------------------------------- // class hashTreeIterator // iterator protocol for hash tree structures //---------------------------------------------------------------------- template class hashTreeIterator : public hashTableIterator, T, T> { public: // constructor hashTreeIterator(hashTree & x); }; //---------------------------------------------------------------------- // class hashVector implementation //---------------------------------------------------------------------- template hashVector:: hashVector(int max, int (*f)(const H &)) : vector(max), hashfun(f) { // no further initialization } template hashVector:: hashVector(int max, int (*f)(const H &), T & initialValue) : vector(max, initialValue), hashfun(f) { // no further initialization } template hashVector:: hashVector(const hashVector & v) : vector(v), hashfun(v.hashfun) { // no further initialization } template T & hashVector:: operator [] (const H & index) { // subscript a hash vector // hash the index value before indexing vector return vector::operator [] ((*hashfun)(index) % size); } //---------------------------------------------------------------------- // class hashTable implementation //---------------------------------------------------------------------- template hashTable:: hashTable(unsigned int max, unsigned int (*f)(const H &)) : tablesize(max), buckets(max), hashfun(f) { // no further initialization } template int hashTable::isEmpty() { // if any table is non-empty, return 0 for (int i = 0; i < tablesize; i++) if (!buckets[i].isEmpty()) return 0; // all empty return 1; } template void hashTable:: deleteAllValues() { // delete all values from a hash table // clear the elements from each of teh buckets for (int i = 0; i < tablesize; i++) buckets[i].deleteAllValues(); } template unsigned int hashTable:: hash(const H & key) const { // return hashed value of key return (*hashfun)(key) % tablesize; } //---------------------------------------------------------------------- // class hashTree implementation //---------------------------------------------------------------------- template hashTree:: hashTree(unsigned int max, unsigned int (*f)(const T &)) : hashTable, T, T>(max, f) { // no further initialization } template void hashTree::add(T newele) { // find the right bucket, then add the element buckets[hash(newele)].add(newele); } template int hashTree::includes(T ele) const { // test to see if the collection includes an element return buckets[hash(ele)].includes(newele); } template void hashTree::remove(T ele) { // remove an element buckets[hash(ele)].remove(newele); } template iterator * hashTree:: makeIterator(unsigned int i) { return new inorderTreeTraversal(buckets[i]); } //---------------------------------------------------------------------- // class hashTableIterator implementation //---------------------------------------------------------------------- template hashTableIterator:: hashTableIterator(hashTable & v) : base(v), currentIndex(0), itr(0) { // no further initialization } template int hashTableIterator:: init() { // initialize iterator, // start search with first bucket currentIndex = 0; itr = 0; return getNextIterator(); } template T hashTableIterator:: operator()() { // return current element return (*itr)(); } template int hashTableIterator:: operator !() { // test if there is a current element return itr != 0; } template int hashTableIterator:: operator ++() { // see if current iterator can be advanced if (itr && (*itr)++) return 1; // if not, get next iterator currentIndex++; return getNextIterator(); } template void hashTableIterator:: operator=(T val) { // change the current value (*itr) = val; } template int hashTableIterator:: getNextIterator() { // if there is an old iterator, delete it if (itr != 0) delete itr; // now search for a new one for (; currentIndex < base.tablesize; currentIndex++) { // generate a new iterator at the current point itr = base.makeIterator(currentIndex); assert(itr != 0); // if it has at least one element, we're done if (itr->init()) return 1; // otherwise delete it, try again delete itr; } // all out of iterators, can quit itr = 0; return 0; } //---------------------------------------------------------------------- // class hashTreeIterator implementation //---------------------------------------------------------------------- template hashTreeIterator::hashTreeIterator(hashTree & x) : hashTableIterator, T, T>(x) { // no further initialization } //---------------------------------------------------------------------- // miscellaneous template functions //---------------------------------------------------------------------- // bucket sort (version #1) template void bucketSort(vector & data, unsigned int tablesize, unsigned int (*f)(const T &)) { // CFRONT error ?? unsigned int max = data.length(): hashTree table(tablesize, f); // put each element into the appropriate bucket for (unsigned int i = 0; i < max; i++) table.add(x[i]); // now put elements back into vector hashTreeIterator itr(table); int j = 0; for (itr.init(); ! itr; itr++) x[j++] = itr(); } // bucket sort (version #2) template void bucketSort(vector & data, unsigned int (*f)(const T &)) { const int tablesize = 31; unsigned int max = data.length(); orderedList buckets[tablesize]; // put each element into the appropriate bucket for (unsigned int i = 0; i < max; i++) buckets[f(data[i])].add(data[i]); // now put elements back into vector int j = 0; for (i = 0; i < tablesize; i++) { // empty the elements from the bucket listIterator itr(buckets[i]); for (itr.init(); ! itr; itr++) data[j++] = itr(); } } #endif