00001 // hash.h 00002 // Data structures to manage a hash table to relate arbitrary 00003 // keys to arbitrary values. A hash table allows efficient lookup 00004 // for the value given the key. 00005 // 00006 // I've only tested this implementation when both the key and the 00007 // value are primitive types (ints or pointers). There is no 00008 // guarantee that it will work in general. In particular, it 00009 // assumes that the "==" operator works for both keys and values. 00010 // 00011 // In addition, the key must have Hash() defined: 00012 // unsigned Hash(Key k); 00013 // returns a randomized # based on value of key 00014 // 00015 // The value must have a function defined to retrieve the key: 00016 // Key GetKey(T x); 00017 // 00018 // The hash table automatically resizes itself as items are 00019 // put into the table. The implementation uses chaining 00020 // to resolve hash conflicts. 00021 // 00022 // Allocation and deallocation of the items in the table are to 00023 // be done by the caller. 00024 // 00025 // Copyright (c) 1992-1996 The Regents of the University of California. 00026 // All rights reserved. See copyright.h for copyright notice and limitation 00027 // of liability and disclaimer of warranty provisions. 00028 00029 #ifndef HASH_H 00030 #define HASH_H 00031 00032 #include "copyright.h" 00033 #include "list.h" 00034 00035 // The following class defines a "hash table" -- allowing quick 00036 // lookup according to the hash function defined for the items 00037 // being put into the table. 00038 00039 template <class Key,class T> class HashIterator; 00040 00041 template <class Key, class T> 00042 class HashTable { 00043 public: 00044 HashTable(Key (*get)(T x), unsigned (*hFunc)(Key x)); 00045 // initialize a hash table 00046 ~HashTable(); // deallocate a hash table 00047 00048 void Insert(T item); // Put item into hash table 00049 T Remove(Key key); // Remove item from hash table. 00050 00051 bool Find(Key key, T *itemPtr) const; 00052 // Find an item from its key 00053 bool IsInTable(Key key) { T dummy; return Find(key, &dummy); } 00054 // Is the item in the table? 00055 00056 bool IsEmpty() { return numItems == 0; } 00057 // does the table have anything in it 00058 00059 void Apply(void (*f)(T)) const; 00060 // apply function to all elements in table 00061 00062 void SanityCheck() const;// is this still a legal hash table? 00063 void SelfTest(T *p, int numItems); 00064 // is the module working? 00065 00066 private: 00067 typedef List<T> *Bucket; 00068 00069 Bucket *buckets; // the array of hash buckets 00070 int numBuckets; // the number of buckets 00071 int numItems; // the number of items in the table 00072 00073 Key (*getKey)(T x); // get Key from value 00074 unsigned (*hash)(Key x); // the hash function 00075 00076 void InitBuckets(int size);// initialize bucket array 00077 void DeleteBuckets(Bucket *table, int size); 00078 // deallocate bucket array 00079 00080 int HashValue(Key key) const; 00081 // which bucket does the key hash to? 00082 00083 void ReHash(); // expand the hash table 00084 00085 bool FindInBucket(int bucket, Key key, T *itemPtr) const; 00086 // find item in bucket 00087 int FindNextFullBucket(int start) const; 00088 // find next full bucket starting from this one 00089 00090 friend class HashIterator<Key,T>; 00091 }; 00092 00093 // The following class can be used to step through a hash table -- 00094 // same interface as ListIterator. Example code: 00095 // HashIterator<Key, T> iter(table); 00096 // 00097 // for (; !iter->IsDone(); iter->Next()) { 00098 // Operation on iter->Item() 00099 // } 00100 00101 template <class Key,class T> 00102 class HashIterator { 00103 public: 00104 HashIterator(HashTable<Key,T> *table); // initialize an iterator 00105 ~HashIterator() { if (bucketIter != NULL) delete bucketIter;}; 00106 // destruct an iterator 00107 00108 bool IsDone() { return (bucket == table->numBuckets); }; 00109 // return TRUE if no more items in table 00110 T Item() { ASSERT(!IsDone()); return bucketIter->Item(); }; 00111 // return current item in table 00112 void Next(); // update iterator to point to next 00113 00114 private: 00115 HashTable<Key,T> *table; // the hash table we're stepping through 00116 int bucket; // current bucket we are in 00117 ListIterator<T> *bucketIter; // where we are in the bucket 00118 }; 00119 00120 #include "hash.cc" // templates are really like macros 00121 // so needs to be included in every 00122 // file that uses the template 00123 #endif // HASH_H