// hash.h // Data structures to manage a hash table to relate arbitrary // keys to arbitrary values. A hash table allows efficient lookup // for the value given the key. // // I've only tested this implementation when both the key and the // value are primitive types (ints or pointers). There is no // guarantee that it will work in general. In particular, it // assumes that the "==" operator works for both keys and values. // // In addition, the key must have Hash() defined: // unsigned Hash(Key k); // returns a randomized # based on value of key // // The value must have a function defined to retrieve the key: // Key GetKey(T x); // // The hash table automatically resizes itself as items are // put into the table. The implementation uses chaining // to resolve hash conflicts. // // Allocation and deallocation of the items in the table are to // be done by the caller. // // Copyright (c) 1992-1996 The Regents of the University of California. // All rights reserved. See copyright.h for copyright notice and limitation // of liability and disclaimer of warranty provisions. #ifndef HASH_H #define HASH_H #include "copyright.h" #include "list.h" // The following class defines a "hash table" -- allowing quick // lookup according to the hash function defined for the items // being put into the table. template class HashTable { public: HashTable(Key (*get)(T x), unsigned (*hFunc)(Key x)); // initialize a hash table ~HashTable(); // deallocate a hash table void Insert(T item); // Put item into hash table T Remove(Key key); // Remove item from hash table. bool Find(Key key, T *itemPtr) const; // Find an item from its key bool IsInTable(Key key) { T dummy; return Find(key, &dummy); } // Is the item in the table? bool IsEmpty() { return numItems == 0; } // does the table have anything in it void Apply(void (*f)(T)) const; // apply function to all elements in table void SanityCheck() const;// is this still a legal hash table? void SelfTest(T *p, int numItems); // is the module working? private: typedef List *Bucket; Bucket *buckets; // the array of hash buckets int numBuckets; // the number of buckets int numItems; // the number of items in the table Key (*getKey)(T x); // get Key from value unsigned (*hash)(Key x); // the hash function void InitBuckets(int size);// initialize bucket array void DeleteBuckets(Bucket *table, int size); // deallocate bucket array int HashValue(Key key) const; // which bucket does the key hash to? void ReHash(); // expand the hash table bool FindInBucket(int bucket, Key key, T *itemPtr) const; // find item in bucket int FindNextFullBucket(int start) const; // find next full bucket starting from this one friend HashIterator; }; // The following class can be used to step through a hash table -- // same interface as ListIterator. Example code: // HashIterator iter(table); // // for (; !iter->IsDone(); iter->Next()) { // Operation on iter->Item() // } template class HashIterator { public: HashIterator(HashTable *table); // initialize an iterator ~HashIterator() { if (bucketIter != NULL) delete bucketIter;}; // destruct an iterator bool IsDone() { return (bucket == table->numBuckets); }; // return TRUE if no more items in table T Item() { ASSERT(!IsDone()); return bucketIter->Item(); }; // return current item in table void Next(); // update iterator to point to next private: HashTable *table; // the hash table we're stepping through int bucket; // current bucket we are in ListIterator *bucketIter; // where we are in the bucket }; #include "hash.cc" // templates are really like macros // so needs to be included in every // file that uses the template #endif // HASH_H