Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

hash.h

Go to the documentation of this file.
00001 #ifndef __HASH_H
00002 #define __HASH_H
00003 
00004 #include <stdlib.h>
00005 /* Primes
00006 1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
00007 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181
00008 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277
00009 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383
00010 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487
00011 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601
00012 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709
00013 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827
00014 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947
00015 953 967 971 977 983 991 997
00016 */
00017 
00018 inline size_t hashfn(unsigned long l)
00019 {
00020   return l*0x33f3;
00021 }
00022 
00023 inline size_t hash2fn(unsigned long l)
00024 {
00025   return l & 7;
00026 }
00027 /*/
00028 template<class K>size_t hashfn(const K& l)
00029 {
00030   size_t s = 0;
00031   unsigned char* p = (unsigned char*)&l;
00032   for (int i = 0; i < sizeof(K)-1; i++)
00033     {
00034       s = 3*s+(255-p[i]);
00035     }
00036 }
00037 
00038 template<class K>size_t hash2fn(const K& l)
00039 {
00040   unsigned char* p = (unsigned char*)&l;
00041   return 255-p[sizeof(K)-1];
00042 }
00043 */
00044 template<class K, class D>
00045 class hashtable
00046 {
00047  public:
00048   class iterator;
00049   friend class hashtable::iterator;
00050 #ifndef _WINDOWS
00051   private:
00052 #endif
00053   struct keydata
00054   {
00055     K key;
00056     D data;
00057     bool inuse;
00058     keydata() : inuse(false) {}
00059     keydata(K k, D d) : key(k), data(d), inuse(true) {}
00060   };
00061   keydata* table;
00062   size_t hshsz;
00063   bool notprime(size_t p)
00064   {
00065     size_t d;
00066     if (p % 2 == 0) return true;
00067     d = 3;
00068     while (d*d <= p)
00069     {
00070       if (p % d == 0)
00071         {
00072           return true;
00073         }
00074       d += 2;
00075     }
00076     return false;
00077   }
00078   void resize()
00079     {
00080       size_t oldsz = hshsz;
00081       hshsz = (3*hshsz)/2;
00082       while (notprime(hshsz))
00083         {
00084           hshsz++;
00085         }
00086       //printf("Size:%u\n", hshsz);
00087       keydata* oldtable = table;
00088       table = new keydata[hshsz];
00089       for (size_t i = 0; i < oldsz; i++)
00090         {
00091           if (oldtable[i].inuse)
00092             {
00093               //printf("Setting %u to %u\n", oldtable[i].key, oldtable[i].data);
00094               (*this)[oldtable[i].key] = oldtable[i].data;
00095               //printf("Now %u is %u\n", oldtable[i].key, (*this)[oldtable[i].key]);
00096             }
00097         }
00098       delete [] oldtable;
00099     }
00100   size_t findkey(const K& key) // returns -1 if can't find it
00101   {
00102     size_t hash2 = hash2fn(key)%(hshsz-1)+1;
00103     size_t hash = hashfn(key) % hshsz;
00104     size_t i = hash;
00105     //printf("Key:%u, hash:%u, hash2:%u\n", key, hash, hash2);
00106     while (table[i].inuse) // !empty
00107       {
00108         if (table[i].key == key)
00109           {
00110             //printf("Key %u present at %u\n", key, i);
00111             return i; // but its the correct one & present
00112           }
00113         i = (i+hash2) % hshsz;
00114         if (i == hash) // Table full
00115           {
00116             resize();
00117             hash2 = hash2fn(key)%(hshsz-1)+1;
00118             hash = hashfn(key) % hshsz;
00119             i = hash;
00120             //printf("(R)Key:%u, hash:%u, hash2:%u\n", key, hash, hash2);
00121           }
00122       }
00123     //printf("Key %u absent at %u\n", key, i);
00124     return i; // found & absent
00125   }
00126  public:
00127   hashtable(int sz) : hshsz(sz)
00128     {
00129       while (notprime(hshsz))
00130         {
00131           hshsz++;
00132         }
00133       //printf("Size:%u\n", hshsz);
00134       table = new keydata[hshsz];
00135     }
00136   ~hashtable()
00137     {
00138       delete [] table;
00139     }
00140   D& operator[](K k)
00141     {
00142       int i = findkey(k);
00143       table[i].key = k;
00144       table[i].inuse = true;
00145       return table[i].data;
00146     }
00147   class iterator
00148     {
00149       friend class hashtable;
00150 #ifdef _WINDOWS
00151   public:
00152 #endif
00153       unsigned int ptr;
00154       hashtable* tab;
00155       iterator(int t, hashtable* _tab) : ptr(t), tab(_tab)
00156         {
00157           while (!tab->table[ptr].inuse && ptr < tab->hshsz)
00158             {
00159               ptr++;
00160             }
00161         }
00162     public:
00163       iterator() : tab(NULL) {}
00164       iterator operator++()
00165         {
00166           while (++ptr < tab->hshsz)
00167             {
00168               if (tab->table[ptr].inuse) return *this;
00169             }
00170           return *this;
00171         }
00172       iterator& operator=(const iterator& r)
00173         {
00174           ptr = r.ptr;
00175           tab = r.tab;
00176           return *this;
00177         }
00178       bool operator!=(const iterator& r)
00179         {
00180           return !((ptr == r.ptr) && (tab == r.tab));
00181         }
00182       bool operator==(const iterator& r)
00183         {
00184           return ((ptr == r.ptr) && (tab == r.tab));
00185         }
00186       K first() { return tab->table[ptr].key; }
00187       D second() { return tab->table[ptr].data; }
00188     };
00189   iterator find(K k)
00190     {
00191       size_t i = findkey(k);
00192       return (table[i].inuse) ? iterator(i,this) :  end();
00193     }
00194   D& operator[](const iterator& i) // Never call with an invalid iterator!
00195     {
00196       return table[i.ptr].data;
00197     }
00198   iterator begin() { return iterator(0, this); }
00199   iterator end() { return iterator(hshsz, this); }
00200 };
00201 #endif

Generated on Sat Nov 5 16:16:55 2005 for OPIE by  doxygen 1.4.2