Main Page   Class Hierarchy   Compound List   File List   Compound Members  

TValHashSetT.hh

00001 #ifndef _T_VAL_HASH_SET_T_HH
00002 #define _T_VAL_HASH_SET_T_HH
00003 
00004 #include <stdio.h>
00005 #include <stdlib.h>
00006 #include "TMemoryException.hh"
00007 
00008 
00009 // Template class used to hold one key in a TValHashSetT object.
00010 
00011 template <class K>
00012 class TValHashSetEntryT
00013 {
00014 public:
00015   
00019   TValHashSetEntryT (const K& k)
00020     : key (k)
00021   {
00022   }
00023   
00025   TValHashSetEntryT *next;
00026   
00028   unsigned int hash;
00029   
00031   K key;
00032 };
00033 
00034 
00050 template <class K, class U>
00051 class TValHashSetT
00052 {
00053 public:
00054   
00058   TValHashSetT ();
00059   
00063   TValHashSetT (const TValHashSetT<K,U> &set) { Copy (set); }
00064   
00068   ~TValHashSetT ();
00069   
00076   void Apply (void (*fn)(const K *, void *), void *d);
00077   
00081   void Clear ();
00082   
00089   bool Contains (const K& k);
00090   
00096   int Entries () { return myNumEntries; }
00097   
00104   bool Insert (const K& k);
00105   
00112   bool Remove (const K& k);
00113   
00120   void Shrink (bool flag) { myIsShrinkEnabled = flag; }
00121   
00125   TValHashSetT<K,U>& operator=(const TValHashSetT<K,U> &set);
00126   
00127 private:
00128  
00133   void Copy (const TValHashSetT<K,U>& set);
00134   
00138   void Grow ();
00139   
00146   void ReHash (int new_num_buckets);
00147 
00151   void Shrink ();
00152   
00153   
00155   TValHashSetEntryT<K> **myBuckets;
00156   
00158   int myNumBuckets;
00159   
00161   int myBucketMask;
00162   
00165   int myShrinkSize;
00166   
00169   int myGrowSize;
00170   
00172   int myNumEntries;
00173   
00175   bool myIsShrinkEnabled;
00176   
00179   static const int BUCKET_MULTIPLIER;
00180   
00182   static const int NUM_BUCKETS;
00183 };
00184 
00185 
00186 template <class K, class U>
00187 const int TValHashSetT<K,U>::BUCKET_MULTIPLIER = 3;
00188 
00189 template <class K, class U>
00190 const int TValHashSetT<K,U>::NUM_BUCKETS = 4;
00191 
00192 
00193 template <class K, class U>
00194 TValHashSetT<K,U>::TValHashSetT ()
00195   : myNumBuckets (NUM_BUCKETS),
00196     myBucketMask (NUM_BUCKETS - 1),
00197     myGrowSize (NUM_BUCKETS * BUCKET_MULTIPLIER),
00198     myNumEntries (0),
00199     myIsShrinkEnabled (true)
00200 {
00201   myBuckets = (TValHashSetEntryT<K> **)
00202     calloc (myNumBuckets, sizeof (myBuckets));
00203   
00204   if (! myBuckets)
00205     throw TMemoryException ();
00206 }
00207 
00208 
00209 template <class K, class U>
00210 TValHashSetT<K,U>::~TValHashSetT ()
00211 {
00212   myIsShrinkEnabled = false;
00213   Clear ();
00214   free (myBuckets);
00215 }
00216 
00217 
00218 template <class K, class U>
00219 void TValHashSetT<K,U>::Apply (void (*fn)(const K *, void *), void *d)
00220 {
00221   TValHashSetEntryT<K> *entry;
00222   
00223   for (int i = 0; i < myNumBuckets; i++)
00224     {
00225       entry = myBuckets[i];
00226       while (entry)
00227         {
00228           fn (&entry->key, d);
00229           entry = entry->next;
00230         }
00231     }
00232 }
00233 
00234 
00235 template <class K, class U>
00236 void TValHashSetT<K,U>::Clear ()
00237 {
00238   TValHashSetEntryT<K> *entry, *tmp_entry;
00239   
00240   if (myNumEntries)
00241     {
00242       for (int i = 0; i < myNumBuckets; i++)
00243         {
00244           entry = myBuckets[i];
00245           while (entry)
00246             {
00247               tmp_entry = entry;
00248               entry = entry->next;
00249               delete tmp_entry;
00250             }
00251           
00252           myBuckets[i] = 0;
00253         }
00254       
00255       myNumEntries = 0;
00256     }
00257   
00258   if (myIsShrinkEnabled)
00259     {
00260       myNumBuckets = NUM_BUCKETS;
00261       myBucketMask = NUM_BUCKETS - 1;
00262       myGrowSize = NUM_BUCKETS * BUCKET_MULTIPLIER;
00263       
00264       myBuckets = (TValHashSetEntryT<K> **)
00265         realloc (myBuckets, myNumBuckets * sizeof (myBuckets));
00266     }
00267 }
00268 
00269 
00270 template <class K, class U>
00271 bool TValHashSetT<K,U>::Contains (const K& k)
00272 {
00273   TValHashSetEntryT<K> *entry;
00274   unsigned int hash = U::Hash (k);
00275   
00276   entry = myBuckets[hash & myBucketMask];
00277   while (entry)
00278     {
00279       if (entry->hash == hash &&
00280           U::Equal (k, entry->key))
00281         return true;
00282       
00283       entry = entry->next;
00284     }
00285   
00286   return false;
00287 }
00288 
00289 
00290 template <class K, class U>
00291 bool TValHashSetT<K,U>::Insert (const K& k)
00292 {
00293   TValHashSetEntryT<K> *entry, *old_entry;
00294   unsigned int hash = U::Hash (k);
00295   int index = hash & myBucketMask;
00296   
00297   entry = old_entry = myBuckets[index];
00298   while (entry)
00299     {
00300       if (entry->hash == hash &&
00301           U::Equal (k, entry->key))
00302         return false;
00303       
00304       entry = entry->next;
00305     }
00306   
00307   entry = new TValHashSetEntryT<K> (k);
00308   myBuckets[index] = entry;
00309   entry->next = old_entry;
00310   entry->hash = hash;
00311   
00312   myNumEntries++;
00313   if (myNumEntries >= myGrowSize)
00314     Grow ();
00315   
00316   return true;
00317 }
00318 
00319 
00320 template <class K, class U>
00321 bool TValHashSetT<K,U>::Remove (const K& k)
00322 {
00323   TValHashSetEntryT<K> *entry, *prev = 0;
00324   unsigned int hash = U::Hash (k);
00325   int index = hash & myBucketMask;
00326   
00327   entry = myBuckets[index];
00328   while (entry)
00329     {
00330       if (entry->hash == hash &&
00331           U::Equal (k, entry->key))
00332         {
00333           if (entry == myBuckets[index])
00334             myBuckets[index] = entry->next;
00335           else
00336             prev->next = entry->next;
00337           
00338           delete (entry);
00339           myNumEntries--;
00340           if (myIsShrinkEnabled && myNumBuckets > NUM_BUCKETS &&
00341               myNumEntries <= myShrinkSize)
00342             Shrink ();
00343           
00344           return true;
00345         }
00346       
00347       prev = entry;
00348       entry = entry->next;
00349     }
00350   
00351   return false;
00352 }
00353 
00354 
00355 template <class K, class U>
00356 TValHashSetT<K,U>& TValHashSetT<K,U>::operator=(const TValHashSetT<K,U> &set)
00357 {
00358   /* Only copy if different objects. */
00359   if (&set != this)
00360     {
00361       bool shrink_enabled = myIsShrinkEnabled;
00362 
00363       myIsShrinkEnabled = false;
00364       Clear ();
00365       free (myBuckets);
00366       Copy (set);
00367       myIsShrinkEnabled = shrink_enabled;
00368     }
00369   
00370   return *this;
00371 }
00372 
00373 
00374 template <class K, class U>
00375 void TValHashSetT<K,U>::Copy (const TValHashSetT<K,U>& set)
00376 {
00377   TValHashSetEntryT<K> *orig_entry, *new_entry, *old_entry;
00378   
00379   myNumBuckets = set.myNumBuckets;
00380   myBucketMask = set.myBucketMask;
00381   myShrinkSize = set.myShrinkSize;
00382   myGrowSize = set.myGrowSize;
00383   myNumEntries = set.myNumEntries;
00384   myIsShrinkEnabled = set.myIsShrinkEnabled;
00385   
00386   myBuckets = (TValHashSetEntryT<K> **)
00387     calloc (myNumBuckets, sizeof (myBuckets));
00388   
00389   if (! myBuckets)
00390     throw TMemoryException ();
00391   
00392   for (int i = 0; i < myNumBuckets; i++)
00393     {
00394       orig_entry = set.myBuckets[i];
00395       while (orig_entry)
00396         {
00397           old_entry = myBuckets[i];
00398           new_entry = new TValHashSetEntryT<K> (orig_entry->key);
00399           new_entry->next = old_entry;
00400           new_entry->hash = orig_entry->hash;
00401           myBuckets[i] = new_entry;
00402           orig_entry = orig_entry->next;
00403         }
00404     }
00405 }
00406 
00407 
00408 template <class K, class U>
00409 void TValHashSetT<K,U>::Grow ()
00410 {
00411   ReHash (myNumBuckets << 2);
00412   myShrinkSize = (myNumBuckets * BUCKET_MULTIPLIER) >> 4;
00413   myGrowSize <<= 2;
00414 }
00415 
00416 
00417 template <class K, class U>
00418 void TValHashSetT<K,U>::ReHash (int new_num_buckets)
00419 {
00420   TValHashSetEntryT<K> **orig_buckets = myBuckets;
00421   TValHashSetEntryT<K> *entry, *old_entry, *tmp_entry;
00422   int old_num_buckets = myNumBuckets, index;
00423   
00424   myBuckets = (TValHashSetEntryT<K> **)
00425     calloc (new_num_buckets, sizeof (myBuckets));
00426   
00427   if (! myBuckets)
00428     throw TMemoryException ();
00429   
00430   myNumBuckets = new_num_buckets;
00431   myBucketMask = new_num_buckets - 1;
00432   
00433   for (int i = 0; i < old_num_buckets; i++)
00434     {
00435       entry = orig_buckets[i];
00436       while (entry)
00437         {
00438           tmp_entry = entry;
00439           entry = entry->next;
00440           index = tmp_entry->hash & myBucketMask;
00441           old_entry = myBuckets[index];
00442           myBuckets[index] = tmp_entry;
00443           tmp_entry->next = old_entry;    
00444         }
00445     }
00446   
00447   free (orig_buckets);
00448 }
00449 
00450 
00451 template <class K, class U>
00452 void TValHashSetT<K,U>::Shrink ()
00453 {
00454   ReHash (myNumBuckets >> 2);
00455   myShrinkSize >>= 2;
00456   myGrowSize >>= 2;
00457 }
00458 
00459 #endif // _T_VAL_HASH_SET_T_HH

Generated on Sat Feb 15 18:37:16 2003 for Tools by doxygen1.3-rc2