Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

HashTable.h

Go to the documentation of this file.
00001 // $Header: /nfs/slac/g/glast/ground/cvs/GaudiKernel/GaudiKernel/HashTable.h,v 1.1.1.1 2001/04/18 18:14:18 tlindner Exp $
00002 #ifndef GAUDIKERNEL_HASHTABLE_H
00003 #define GAUDIKERNEL_HASHTABLE_H
00004 
00005 #include <list>
00006 #include <vector>
00007 #include <functional>
00008 
00009 template <class T> class HashTableHasher : public std::unary_function<const T&,size_t>  {
00010 public:
00011   size_t operator()(const T& key)    {
00012     size_t f = size_t(key)>>4;
00013     const unsigned char* s = (const unsigned char*)&f;
00014     return (((((((0^*s++)<<1)^*s++)<<1)^*s++)<<1)^*s++);
00015   }
00016 };
00017 
00042 template < class K, class E, class H=HashTableHasher< K > > 
00043 class HashTable {
00044 public:
00045 
00048   template<class KK, class EE> class TableEntry {
00049     friend class HashTable<KK,EE,H>;
00050   private:
00052     TableEntry* chain;
00053   public:
00055     KK       first;
00057     EE       second;
00059     TableEntry() : chain(0)  {
00060     }
00062     TableEntry(const TableEntry& copy) 
00063     : chain(copy.chain), first(copy.first), second(copy.second) {
00064     }
00066     TableEntry(const KK& k, const EE& e,TableEntry* c)
00067     : chain(c), first(k), second(e) {
00068     }
00070     bool operator==(const TableEntry& copy)     const   {
00071       return copy.first == first;
00072     }
00074     TableEntry& operator=(const TableEntry& copy)   {
00075       first  = copy.first;
00076       second = copy.second;
00077       chain  = copy.chain;
00078       return *this;
00079     }
00080   };
00081   typedef HashTable<K,E,H>               table_type;
00082   typedef H                              hash_type;
00083   typedef TableEntry<K, E>               value_type;
00084   typedef std::list< value_type >        container_type;
00085   typedef container_type::iterator       iterator;
00086   typedef container_type::const_iterator const_iterator;
00087 protected:
00089   int     m_size;
00091   int     m_incr;
00093   std::vector<value_type*> m_vec;
00095   container_type           m_con;
00097   hash_type                m_hash;
00098 protected:
00100   void rehash(int new_size)   {
00101     m_vec.clear();
00102     m_vec.insert(m_vec.begin(), new_size, (value_type*)0);
00103     for ( container_type::iterator i = m_con.begin(); i != m_con.end(); i++ )    {
00104       size_t h   = m_hash((*i).first)%m_vec.size();
00105       (*i).chain = m_vec[h];
00106       m_vec[h]   = &(*i);
00107     }
00108   }
00110   value_type* find(size_t idx, const K& key )    {
00111     for (value_type* e = m_vec[idx]; e != 0; e = e->chain)    {
00112       if ( e->first == key )  {
00113         return e;
00114       }
00115     }
00116     return 0;
00117   }
00118   void remove(value_type* e)  {
00119     m_con.remove(*e);
00120     m_size--;
00121   }
00122 public:
00124   HashTable(int length = 16, int incr = 2) : m_size(0), m_incr(incr)  {
00125     reserve(length);
00126   }
00128   virtual ~HashTable()    {
00129     clear();
00130   }
00132   iterator begin()    {
00133     return m_con.begin();
00134   }
00136   const_iterator begin()   const  {
00137     return m_con.begin();
00138   }
00140   iterator end()    {
00141     return m_con.end();
00142   }
00144   const_iterator end()   const  {
00145     return m_con.end();
00146   }
00148   void clear()      {
00149     m_con.erase(m_con.begin(), m_con.end());
00150     m_vec.erase(m_vec.begin(), m_vec.end());
00151   }
00153   long size()   const   {
00154     return m_size;
00155   }
00157   void reserve(int len)   {
00158     if ( int(m_vec.size()) < len ) rehash(len);
00159   }
00161   bool insert(const K& first, const E& second)     {
00162     size_t h = m_hash(first)%m_vec.size();
00163     value_type* val = find(h, first);
00164     if ( !val )    {
00165       if ( ++m_size == int(m_vec.size()) )   {
00166         rehash(m_vec.size()*m_incr);
00167         h = m_hash(first)%m_vec.size();
00168       }
00169       m_con.insert(m_con.end(), value_type(first, second, m_vec[h]));
00170       m_vec[h] = &m_con.back();
00171       return true;
00172     }
00173     return false;
00174   }
00176   value_type* find(const K& first)    {
00177     return find(m_hash(first)%m_vec.size(), first);
00178   }
00180   const value_type* find(const K& first) const    {
00181     table_type* thisPtr = const_cast<table_type*>(this);
00182     return thisPtr->find(m_hash(first)%m_vec.size(), first);
00183   }
00185   void remove(const K& first)    {
00186     size_t h = m_hash(first)%m_vec.size();
00187     if (0 != m_vec[h])     {
00188       value_type *prev, *e = m_vec[h];
00189       if ( e->first == first )   {
00190         m_vec[h] = e->chain;
00191         remove(e);
00192         return;
00193       } 
00194       do    {
00195         prev = e;
00196         e = e->chain;
00197       } while ( 0 != e && e->first != first);
00198       if ( 0 != e )  {
00199         prev->chain = e->chain;
00200         remove(e);
00201       }
00202     }
00203   }
00204 };
00205 
00206 #endif    // GAUDI_KERNEL_HASHTABLE_H

Generated at Wed Nov 21 12:22:03 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000