hash.inc

Go to the documentation of this file.
00001 
00029 #ifndef ABA_HASH_INC
00030 #define ABA_HASH_INC
00031 
00032 #ifdef ABACUS_PARALLEL
00033 #include "abacus/id.h"
00034 
00035 #endif
00036 #include "abacus/string.h"
00037 
00038 #include <math.h>
00039 
00040   template <class KeyType, class ItemType>
00041   inline ABA_HASHITEM<KeyType, ItemType>::ABA_HASHITEM(
00042          const KeyType &key, 
00043          const ItemType &item) :  
00044     key_(key),  
00045     item_(item),  
00046     next_(0)
00047   {  }
00048 
00049   template <class KeyType, class ItemType>
00050   ostream &operator<<(ostream &out, const ABA_HASHITEM<KeyType, ItemType> &rhs)
00051   {
00052     return out << '(' << rhs.key_ << ',' << rhs.item_ << ')';
00053   }
00054 
00055   template <class KeyType, class ItemType>
00056   inline ABA_HASHITEM<KeyType, ItemType> * ABA_HASHITEM<KeyType, 
00057      ItemType>::next()
00058   {
00059     return next_;
00060   }
00061 
00062   template <class KeyType, class ItemType>
00063   ABA_HASH<KeyType, ItemType>::ABA_HASH(ABA_GLOBAL *glob, int size)
00064   :  
00065     glob_(glob),  
00066     size_(size),  
00067     nCollisions_(0),  
00068     iter_(0)
00069   {  
00070 #ifdef ABACUS_OLD_NEW
00071     typedef ABA_HASHITEM<KeyType, ItemType>* pABA_HASHITEM;
00072     table_ = new pABA_HASHITEM[size];
00073 #else
00074     table_ = new ABA_HASHITEM<KeyType, ItemType>* [size];
00075 #endif
00076 
00077     for (int i = 0; i < size; i++) table_[i] = 0;
00078   }
00079 
00080   template <class KeyType, class ItemType>
00081   ABA_HASH<KeyType, ItemType>::~ABA_HASH()
00082   {
00083     ABA_HASHITEM<KeyType, ItemType> *h1;
00084     ABA_HASHITEM<KeyType, ItemType> *h2;
00085     int i;
00086     
00087     for (i = 0; i < size_; i++) {
00088       if((h1 = table_[i])) 
00089         while (h1) {
00090           h2 = h1->next_;
00091           delete h1;
00092           h1 = h2;
00093         }
00094     }
00095     delete [] table_;
00096   }
00097 
00098   template <class KeyType, class ItemType>
00099   ostream &operator<<(ostream &out, const ABA_HASH<KeyType, ItemType> &hash)
00100   {
00101 
00102     ABA_HASHITEM<KeyType, ItemType> *h;
00103     const int s = hash.size();
00104     
00105     for (int i = 0; i < s; i++) {
00106       h = hash.table_[i];
00107       if (h) {
00108         out << i << ':';
00109         while(h) {
00110           out << *h << ' ';
00111           h = h->next();
00112         }  
00113         out << endl;
00114       }  
00115     }  
00116     return out;
00117   }
00118 
00119   template <class KeyType, class ItemType>
00120   void ABA_HASH<KeyType, ItemType>::insert(const KeyType &key, 
00121                                            const ItemType &item)
00122   {
00123     ABA_HASHITEM<KeyType, ItemType> *h = new ABA_HASHITEM<KeyType, ItemType>(key, item);
00124     int slotNum = hf(key);
00125 
00126     if (table_[slotNum]) ++nCollisions_;
00127     h->next_ = table_[slotNum];
00128     table_[slotNum] = h;
00129 
00130   }
00131 
00132   template <class KeyType, class ItemType>
00133   void ABA_HASH<KeyType, ItemType>::overWrite(const KeyType &key, 
00134                                               const ItemType &item)
00135   {
00137     int slotNum = hf(key);
00138     if (table_[slotNum]) ++nCollisions_;
00139 
00140     ABA_HASHITEM<KeyType, ItemType> *h = table_[slotNum];
00141 
00143 
00145     while (h) {
00146       if (h->key_ == key) {
00147         h->item_ = item;
00148         return;
00149       }
00150       h = h->next_;
00151     }
00152 
00154     h               = new ABA_HASHITEM<KeyType, ItemType>(key, item);
00155     h->next_        = table_[slotNum];
00156     table_[slotNum] = h;
00157 
00158   }
00159 
00160   template <class KeyType, class ItemType>
00161   ItemType * ABA_HASH<KeyType, ItemType>::find(const KeyType &key)
00162   {
00163     ABA_HASHITEM<KeyType, ItemType> *slot;
00164 
00165     slot = table_[hf(key)];
00166 
00167     while (slot) {
00168       if (key == slot->key_) return &(slot->item_);
00169       slot = slot->next_;
00170     }
00171     return 0;
00172   }
00173 
00174   template <class KeyType, class ItemType>
00175   bool ABA_HASH<KeyType, ItemType>::find (const KeyType &key, const ItemType &item)
00176   {
00177     ABA_HASHITEM<KeyType, ItemType> *slot;
00178 
00179     slot = table_[hf(key)];
00180 
00181     while (slot) {
00182       if (key == slot->key_ && slot->item_ == item) return true;
00183       slot = slot->next_;
00184     }
00185     return false;
00186   }
00187 
00188   template <class KeyType, class ItemType>
00189   ItemType *ABA_HASH<KeyType, ItemType>::initializeIteration(const KeyType &key)
00190   {
00191     iter_ = table_[hf(key)];
00192     while (iter_) {
00193       if (key == iter_->key_) return &(iter_->item_);
00194       iter_ = iter_->next_;
00195     }
00196     return 0;
00197   }
00198 
00199   template <class KeyType, class ItemType>
00200   ItemType *ABA_HASH<KeyType, ItemType>::next(const KeyType &key)
00201   {
00202     if (iter_ == 0) return 0;
00203     iter_ = iter_->next_;
00204 
00205     while (iter_) {
00206       if (key == iter_->key_) return &(iter_->item_);
00207       iter_ = iter_->next();
00208     }
00209     return 0;
00210   }
00211 
00212   template <class KeyType, class ItemType>
00213   int ABA_HASH<KeyType, ItemType>::remove(const KeyType &key)
00214   {
00215     // remove(): find the slot and return if it is empty
00216     ABA_HASHITEM<KeyType, ItemType> *h1;
00217     ABA_HASHITEM<KeyType, ItemType> *h2;
00218     int slotNum = hf(key);
00219 
00220     h1 = table_[slotNum];
00221     if (h1 == 0)
00222        return 1;
00223 
00224     // check if the first item is being removed
00225     if (h1->key_ == key) {
00226       table_[slotNum] = h1->next_;
00227       delete h1;
00228       return 0;
00229     }
00230 
00231     // otherwise, go through the linked list
00232     while ((h2 = h1->next_)) {
00233       if (h2->key_ == key) {
00234         h1->next_ = h2->next_;
00235         delete h2;
00236         return 0;
00237       }
00238       h1 = h2;
00239     }
00240     return 1;
00241   }
00242 
00243   template <class KeyType, class ItemType>
00244   int ABA_HASH<KeyType, ItemType>::remove(const KeyType &key, const ItemType &item)
00245   {
00246     // remove(): find the slot and return if it is empty
00247     ABA_HASHITEM<KeyType, ItemType> *h1;
00248     ABA_HASHITEM<KeyType, ItemType> *h2;
00249     int slotNum = hf(key);
00250 
00251     h1 = table_[slotNum];
00252     if (h1 == 0)
00253       return 1;
00254 
00255     // check \a key and \a item of the head of the list
00256     if (h1->key_ == key && h1->item_ == item) {
00257       table_[slotNum] = h1->next_;
00258       delete h1;
00259       return 0;
00260     }
00261 
00262     // check \a key and \a item of the other elements of the list
00263     while ((h2 = h1->next_)) {
00264       if (h2->key_ == key && h2->item_ == item) {
00265         h1->next_ = h2->next_;
00266         delete h2;
00267         return 0;
00268       }
00269       h1 = h2;
00270     }
00271     return 1;
00272 
00273   }
00274 
00275   template <class KeyType, class ItemType>
00276   inline int ABA_HASH<KeyType, ItemType>::size() const
00277   {
00278     return size_;
00279   }
00280 
00281   template <class KeyType, class ItemType>
00282   inline int ABA_HASH<KeyType, ItemType>::nCollisions() const
00283   {
00284     return nCollisions_;
00285   }
00286   
00287   template <class KeyType, class ItemType>
00288   inline int ABA_HASH<KeyType, ItemType>::hf(int key)
00289   {
00290     if (key < 0) key = -key;
00291 
00292     double x = key*0.6180339887;
00293 
00294     return (int) (size()*(x-floor(x)));
00295   }
00296 
00297   template <class KeyType, class ItemType>
00298   inline int ABA_HASH<KeyType, ItemType>::hf(unsigned key)
00299   {
00300     double x = key*0.6180339887;
00301 
00302     return (int) (size()*fmod(x, 1.0));
00303   }
00304 
00305   template <class KeyType, class ItemType>
00306   int ABA_HASH<KeyType, ItemType>::hf(const ABA_STRING &string)
00307   {
00308 
00309     const int prime = 516595003;
00310     const int mult  = 314159;
00311     const int s     = string.size();
00312     int h = 0;
00313     for (int i = 0; i < s; i++) {
00314       h += (h ^ (h >> 1)) + mult * (unsigned char) string[i];
00315       while (h >= prime) h -= prime;
00316     }
00317 
00318     return h % s;
00319   }
00320 
00321 #ifdef ABACUS_PARALLEL
00322 
00323   template <class KeyType, class ItemType>
00324   int ABA_HASH<KeyType, ItemType>::hf(const ABA_ID &id)
00325   {
00326     const int rand[64] = {
00327       0x08fa735c, 0x465969d0, 0x66a657f4, 0x144d2cf9,
00328       0x32b20675, 0x7d86036c, 0x3bcd2f61, 0x30421197,
00329       0x272d9013, 0x1d3bf099, 0x1bd38ed1, 0x57abc10e,
00330       0x7e62fbf6, 0x0b9bf7ad, 0x15bd99d9, 0x451a0198,
00331       0x73b3a879, 0x325eeb8a, 0x1dbb0b7c, 0x5bec0be6,
00332       0x2e78432e, 0x2e2ceea6, 0x55177a1a, 0x7b31a98f,
00333       0x54d04dd5, 0x547bd0d0, 0x1d12c33a, 0x16fb478f,
00334       0x687e3120, 0x4a047b2e, 0x649e29fb, 0x1c36b5ae,
00335       0x3a9e8db8, 0x6488c827, 0x5b6315fa, 0x60b4e7c1,
00336       0x5c116177, 0x336ead28, 0x7dcdd34c, 0x41b4bb6e,
00337       0x3f7aeaa3, 0x687cf590, 0x19469807, 0x56a508f0,
00338       0x179ed4c4, 0x06e73a00, 0x007da2a3, 0x41e5ac24,
00339       0x0585b479, 0x5b1cf529, 0x285b5b9a, 0x3bbaea37,
00340       0x7c84f882, 0x081c97ba, 0x6df23bc6, 0x1f655ecb,
00341       0x291ac2ac, 0x7598ef40, 0x5b8235b8, 0x25ccaa59,
00342       0x65a52132, 0x2cf89028, 0x1d05cf45, 0x32e86c2b
00343     };
00344 
00345     return (rand[id.proc() & 63] ^ id.sequence()) % size_;
00346   }
00347 
00348 #endif
00349 
00350   template <class KeyType, class ItemType>
00351   void ABA_HASH<KeyType, ItemType>::resize(int newSize)
00352   {
00353     // check the value of \a newSize
00354     if (newSize <= 0) {
00355       ABA_HASH<KeyType, ItemType>::glob_->err() << "ABA_HASH::resize(): new size of hash table must be ";
00356       ABA_HASH<KeyType, ItemType>::glob_->err() << "positive." << endl;
00357       exit(Fatal);
00358     }
00359 
00360     // allocate a new hash table
00361     /* We have to set the entries of the new hash table to 0 that we 
00362      * can insert the items in the linear lists of the slots in a simple way later.
00363      */
00364     ABA_HASHITEM<KeyType, ItemType> **newTable;
00365 
00366 #ifdef ABACUS_OLD_NEW
00367     typedef ABA_HASHITEM<KeyType, ItemType>* pABA_HASHITEM;
00368     newTable = new pABA_HASHITEM[newSize];
00369 #else
00370     newTable = new ABA_HASHITEM<KeyType, ItemType>* [newSize];
00371 #endif
00372 
00373     for (int i = 0; i < newSize; i++) 
00374       newTable[i] = 0;
00375 
00376     // insert all elements of the old table into the new table
00377     /* We cannot make copies of slots of the old hash tables but have to reinsert
00378      * all elements into the new hash table since the hash function might have
00379      * changed. For efficieny we move each hash item to the new slot.
00380      *
00381      * We replace already here the old size with the new size of the hash table,
00382      * because we need the hash function according to the new size.
00383      */
00384     int oldSize = size_;
00385     size_       = newSize;
00386 
00387 #ifdef ABACUS_NO_FOR_SCOPE
00388     for (i = 0; i < oldSize; i++)
00389 #else
00390     for (int i = 0; i < oldSize; i++) 
00391 #endif
00392     if (table_[i]) {
00393       // move the items to the corresponding new slots
00394       ABA_HASHITEM<KeyType, ItemType> *current = table_[i];
00395       ABA_HASHITEM<KeyType, ItemType> *next;
00396 
00397       while (current) {
00398         int slotNum = hf(current->key_);
00399         next = current->next_;
00400 
00401         current->next_    = newTable[slotNum];
00402         newTable[slotNum] = current;
00403         current           = next;
00404       }
00405 
00406     }
00407 
00408     // replace the old table by the new one
00409     delete table_;
00410     table_ = newTable;
00411 
00412   }
00413 
00414 #endif   // ABA_HASH_INC
00415 

Generated on Tue Aug 14 18:09:53 2007 for ABACUS by  doxygen 1.5.1