LongHash.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __LONGHASH_H__
00019 #define __LONGHASH_H__
00020
00021 #include "Error.h"
00022
00023 #include <limits.h>
00024
00025 #ifdef UINT_MAX
00026 #define LH_NOTFOUND (UINT_MAX)
00027 #else
00028 #define LH_NOTFOUND 0xFFFFFFFF
00029 #endif
00030
00031 template <class ObjectT> class LongHash
00032 {
00033 protected:
00034 ObjectT * objects;
00035 long long * keys;
00036 bool * occupancy;
00037 unsigned int count, size;
00038 unsigned int mask;
00039 bool allowDuplicates;
00040
00041 public:
00042 LongHash(int startsize = 32)
00043 {
00044 count = 0;
00045 size = startsize;
00046 mask = startsize - 1;
00047
00048
00049 if (startsize & mask)
00050 error("LongHash: Hash table size must be a power of two.\n");
00051
00052 occupancy = new bool [size];
00053 objects = new ObjectT [size];
00054 keys = new long long [size];
00055
00056 allowDuplicates = false;
00057
00058 for (unsigned int i = 0; i < size; i++)
00059 {
00060 occupancy[i] = false;
00061 }
00062 };
00063
00064 ~LongHash()
00065 {
00066 delete [] occupancy;
00067 delete [] objects;
00068 delete [] keys;
00069 }
00070
00071 void Grow()
00072 {
00073 SetSize(size * 2);
00074 }
00075 void Shrink()
00076 {
00077 SetSize(size / 2);
00078 }
00079
00080 void SetSize(int newsize)
00081 {
00082 int newmask = newsize - 1;
00083
00084 bool * newoccupancy = new bool [newsize];
00085 ObjectT * newobjects = new ObjectT [newsize];
00086 long long * newkeys = new long long [newsize];
00087
00088 for (int i = 0; i < newsize; i++)
00089 newoccupancy[i] = false;
00090
00091 if (count)
00092 for (unsigned int i = 0; i < size; i++)
00093 if (occupancy[i] != false)
00094 {
00095 long long key = keys[i];
00096 unsigned int h = newmask & (unsigned int) key;
00097
00098 while (newoccupancy[h] == true && (newkeys[h] != key || allowDuplicates))
00099 h = (h + 1) & newmask;
00100
00101 if (newoccupancy[h])
00102 count--;
00103
00104 newkeys[h] = key;
00105 newobjects[h] = objects[i];
00106 newoccupancy[h] = true;
00107 }
00108
00109 delete [] occupancy;
00110 delete [] objects;
00111 delete [] keys;
00112
00113 occupancy = newoccupancy;
00114 objects = newobjects;
00115 keys = newkeys;
00116 size = newsize;
00117 mask = newmask;
00118 }
00119
00120 void Clear()
00121 {
00122 count = 0;
00123
00124 if (size > 32)
00125 SetSize(32);
00126
00127 for (unsigned int i = 0; i < size; i++)
00128 occupancy[i] = false;
00129 }
00130
00131 int Capacity() const
00132 {
00133 return size;
00134 }
00135 int Entries() const
00136 {
00137 return count;
00138 }
00139
00140 ObjectT Object(int i) const
00141 {
00142 return objects[i];
00143 }
00144 ObjectT & Object(int i)
00145 {
00146 return objects[i];
00147 }
00148
00149 void SetObject(int i, ObjectT object)
00150 {
00151 objects[i] = object;
00152 }
00153
00154 unsigned int Add(long long key, ObjectT object)
00155 {
00156 if (count * 2 > size)
00157 Grow();
00158
00159 unsigned int h = Iterate(key);
00160
00161 while (allowDuplicates && occupancy[h] && objects[h] != object)
00162 h = ReIterate(key, h);
00163
00164 if (!occupancy[h])
00165 {
00166 occupancy[h] = true;
00167 keys[h] = key;
00168 count++;
00169 }
00170
00171 objects[h] = object;
00172
00173 return h;
00174 }
00175
00176 unsigned int Find(long long key)
00177 {
00178 unsigned int h = Iterate(key);
00179
00180 return occupancy[h] ? h : LH_NOTFOUND;
00181 }
00182
00183 unsigned int Rehash(long long key, unsigned int h)
00184 {
00185 h = ReIterate(key, h);
00186
00187 return occupancy[h] ? h : LH_NOTFOUND;
00188 }
00189
00190 LongHash & operator = (const LongHash & rhs);
00191
00192 ObjectT operator [](int i) const
00193 {
00194 return objects[i];
00195 }
00196 ObjectT operator [](unsigned int i) const
00197 {
00198 return objects[i];
00199 }
00200
00201 void Delete(unsigned int index)
00202 {
00203 if (index >= size || !occupancy[index])
00204 return;
00205
00206 occupancy[index] = false;
00207 count--;
00208
00209 if (count * 8 < size && size > 32)
00210 Shrink();
00211 else
00212 {
00213
00214 index = (index + 1) & mask;
00215
00216 while (occupancy[index])
00217 {
00218 if ((keys[index] & mask) != index)
00219 {
00220 unsigned int h = Iterate(keys[index]);
00221
00222 while (occupancy[h] && objects[h] != objects[index])
00223 h = ReIterate(keys[index], h);
00224
00225 if (h != (unsigned int) index)
00226 {
00227 keys[h] = keys[index];
00228 occupancy[h] = true;
00229 objects[h] = objects[index];
00230
00231 occupancy[index] = false;
00232 }
00233 }
00234
00235 index = (index + 1) & mask;
00236 }
00237 }
00238 }
00239
00240
00241 bool SlotInUse(int index) const
00242 {
00243 return occupancy[index] == true;
00244 }
00245 bool SlotInUse(unsigned int index) const
00246 {
00247 return occupancy[index] == true;
00248 }
00249
00250
00251 long long GetKey(int index) const
00252 {
00253 return keys[index];
00254 }
00255
00256 long long GetKey(const unsigned int index) const
00257 {
00258 return keys[index];
00259 }
00260
00261 void SetAllowDuplicateKeys(bool toggle)
00262 {
00263 allowDuplicates = toggle;
00264
00265 if (count && !allowDuplicates)
00266 SetSize(size);
00267 }
00268
00269 private:
00270 unsigned int Iterate(long long key) const
00271 {
00272 unsigned int h = mask & (unsigned int) key;
00273
00274 while (occupancy[h] == true && keys[h] != key)
00275 h = (h + 1) & mask;
00276
00277 return h;
00278 }
00279
00280 unsigned int ReIterate(long long key, unsigned int h) const
00281 {
00282 h = (h + 1) & mask;
00283
00284 while (occupancy[h] == true && keys[h] != key)
00285 h = (h + 1) & mask;
00286
00287 return h;
00288 }
00289 };
00290
00291 #endif