Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

GLIBHash.h

Go to the documentation of this file.
00001 #ifndef MMANN_GLIBHASH_H
00002 #define MMANN_GLIBHASH_H
00003 
00011 
00012 
00013 #include "CompareAlgorithms.h"
00014 #include "HashAlgorithms.h"
00015 
00017 #define GLIB_HASH_TABLE_MIN_SIZE        11
00018 
00019 #define GLIB_HASH_TABLE_MAX_SIZE        13845163
00020 
00024 template <class Key>
00025 class GLIBHashNode
00026 {
00027 public:
00029     GLIBHashNode(Key* key, int Value, DeleteHashDataEnum DeleteHashData);
00030 
00032     virtual ~GLIBHashNode();
00033 
00035     Key*  m_Key;
00036 
00038     int m_Value;
00039 
00041     GLIBHashNode<Key>* m_Next;
00042 
00044     DeleteHashDataEnum m_DeleteHashData;
00045 };
00046 
00047 template <class Key>
00048 GLIBHashNode<Key>::GLIBHashNode(Key* key, int Value, DeleteHashDataEnum DeleteHashData)
00049 {
00050     m_Key = key;
00051     m_Value = Value;
00052     m_Next = NULL;
00053     m_DeleteHashData = DeleteHashData;
00054 }
00055 
00056 template <class Key>
00057 GLIBHashNode<Key>::~GLIBHashNode()
00058 {
00059     switch(m_DeleteHashData)
00060     {
00061     case NO_DELETE_HASH_ITEM:
00062         break;
00063     case DELETE_HASH_ITEM:
00064         delete m_Key;
00065         break;
00066     case DELETE_HASH_ITEM_ARRAY:
00067         delete [] m_Key;
00068         break;
00069     default:
00070         //This shouldn't happen
00071         assert(false);
00072     }
00073 
00074     if (m_Next != NULL)
00075         delete m_Next;
00076 }
00077 
00081 template <class Key, class ConfigData>
00082 class GLIBHash : public AGenericHash<Key, ConfigData>
00083 {
00084 public:
00086     GLIBHash(int SizeWanted, ACompareNodesAlgorithm<Key, ConfigData>* Compare, 
00087                 AHashAlgorithm<Key>* Hash, DeleteHashDataEnum DeleteHashData = NO_DELETE_HASH_ITEM);
00088 
00090     virtual ~GLIBHash();
00091 
00097     virtual Key* Insert(Key* key, bool OptimizeForCaching);
00098 
00102     void Remove(Key* key);
00103 
00108     int Lookup(Key* key);
00109 
00116     bool LookupExtended(Key* LookupKey, Key** OriginalKey, int** Value);
00117 
00119     void Freeze();
00120 
00122     void Thaw();
00123 
00125     void Resize();
00126 
00131     void ForEach(AProcessHashAlgorithm<Key, ConfigData>* ProcessFunc, ConfigData* UserData);
00132 
00137     unsigned int ForEachRemove(RemoveHashAlgorithm<Key, ConfigData>* RemoveFunc, ConfigData* configData);
00138     
00140     int GetSize();
00141 
00142 protected:
00147     void Insert(Key* key, int Value);
00148 
00153     GLIBHashNode<Key>** LookupNode(Key* key);
00154 
00155 private:
00157     unsigned int  m_Frozen;
00158 
00160     GLIBHashNode<Key> **m_Nodes;
00161 };
00162 
00163 template <class Key, class ConfigData>
00164 GLIBHash<Key, ConfigData>::GLIBHash(int SizeWanted, ACompareNodesAlgorithm<Key, ConfigData>* Compare, 
00165                                     AHashAlgorithm<Key>* Hash, DeleteHashDataEnum DeleteHashData) : AGenericHash<Key, ConfigData>(SizeWanted, Compare, Hash, DeleteHashData)
00166 {
00167     m_Frozen = 0;
00168     m_Nodes = new GLIBHashNode<Key>*[m_Size];
00169     for (int i = 0; i < m_Size; i++)
00170         m_Nodes[i] = NULL;
00171 }
00172 
00173 template <class Key, class ConfigData>
00174 GLIBHash<Key, ConfigData>::~GLIBHash()
00175 {
00176     for (int i = 0;i<m_Size;i++)
00177         delete m_Nodes[i];
00178 
00179     delete [] m_Nodes;
00180 }
00181 
00182 template <class Key, class ConfigData>
00183 Key* GLIBHash<Key, ConfigData>::Insert(Key* key, bool OptimizeForCaching)
00184 {
00185     GLIBHashNode<Key> **Node = LookupNode(key);
00186 
00187     if (*Node != NULL)
00188         return (*Node)->m_Key;
00189 
00190     int HashValue = m_Hash->Hash(key);
00191     Insert(key, HashValue);
00192     return NULL;
00193 }
00194 
00195 template <class Key,class ConfigData>
00196 void GLIBHash<Key, ConfigData>::Insert(Key* key, int Value)
00197 {
00198     GLIBHashNode<Key> **Node = LookupNode(key);
00199   
00200     if (*Node != NULL)
00201         (*Node)->m_Value = Value;
00202 
00203     *Node = new GLIBHashNode<Key>(key, Value, m_DeleteHashData);
00204     m_NumberOfElements++;
00205     if (!m_Frozen)
00206         Resize();
00207 }
00208 
00209 template <class Key, class ConfigData>
00210 void GLIBHash<Key, ConfigData>::Remove(Key* key)
00211 {
00212     GLIBHashNode<Key> **Node = LookupNode(key),
00213                             *DestroyNode;
00214 
00215     if (*Node)
00216     {
00217         DestroyNode = *Node;
00218         (*Node) = DestroyNode->m_Next;
00219         delete DestroyNode;
00220         m_NumberOfElements--;
00221   
00222         if (!m_Frozen)
00223             Resize();
00224     }
00225 }
00226 
00227 template <class Key, class ConfigData>
00228 int GLIBHash<Key, ConfigData>::Lookup(Key* key)
00229 {
00230     GLIBHashNode<Key> *Node = LookupNode(key);
00231   
00232     return Node ? Node->m_Value : 0;
00233 }
00234 
00235 template <class Key, class ConfigData>
00236 bool GLIBHash<Key, ConfigData>::LookupExtended(Key* LookupKey, Key** OriginalKey, int** Value)
00237 {
00238     GLIBHashNode<Key> *Node = LookupNode(LookupKey);
00239   
00240     if (Node)
00241     {
00242         if (OriginalKey)
00243             *OriginalKey = Node->m_Key;
00244         if (Value)
00245             *Value = Node->m_Value;
00246         return true;
00247     }
00248     else
00249         return false;
00250 }
00251 
00252 template <class Key, class ConfigData>
00253 void GLIBHash<Key, ConfigData>::Freeze()
00254 {
00255     m_Frozen++;
00256 }
00257 
00258 template <class Key, class ConfigData>
00259 void GLIBHash<Key, ConfigData>::Thaw()
00260 {
00261     if (m_Frozen)
00262         if (!(--m_Frozen))
00263             Resize();
00264 }
00265 
00266 template <class Key, class ConfigData>
00267 void GLIBHash<Key, ConfigData>::Resize()
00268 {
00269     GLIBHashNode<Key> **NewNodes;
00270     GLIBHashNode<Key> *Node, *Next;
00271     float NodesPerList = (float)m_NumberOfElements/(float)m_Size;
00272     unsigned int HashValue;
00273     int NewSize = FindClosestPrime(m_NumberOfElements);
00274   
00275     if ((NodesPerList > 0.3 || m_Size <= GLIB_HASH_TABLE_MIN_SIZE) &&
00276         (NodesPerList < 3.0 || m_Size >= GLIB_HASH_TABLE_MAX_SIZE))
00277         return;
00278 
00279     if (NewSize == m_Size)
00280         return;
00281   
00282     NewNodes = new GLIBHashNode<Key>*[NewSize];
00283 
00284     for (int a = 0;a<NewSize;a++)
00285         NewNodes[a] = NULL;
00286 
00287     for (int i = 0; i < m_Size; i++)
00288         for (Node = m_Nodes[i]; Node; Node = Next)
00289         {
00290             Next = Node->m_Next;
00291             HashValue = m_Hash->Hash(Node->m_Key) % NewSize;
00292             Node->m_Next = NewNodes[HashValue];
00293             NewNodes[HashValue] = Node;
00294         }
00295   
00296     delete [] m_Nodes;
00297     m_Nodes = NewNodes;
00298     m_Size = NewSize;
00299 }
00300 
00301 template <class Key, class ConfigData>
00302 void GLIBHash<Key, ConfigData>::ForEach(AProcessHashAlgorithm<Key, ConfigData>* ProcessFunc, ConfigData* UserData)
00303 {
00304     GLIBHashNode<Key> *Node;
00305   
00306     for (int i = 0; i < m_Size; i++)
00307         for (Node = m_Nodes[i]; Node; Node = Node->m_Next)
00308             ProcessFunc->ProcessHash(Node->m_Key, Node->m_Value, UserData);
00309 }
00310 
00311 template <class Key, class ConfigData>
00312 unsigned int GLIBHash<Key, ConfigData>::ForEachRemove(RemoveHashAlgorithm<Key, ConfigData>* RemoveFunc, ConfigData* configData)
00313 {
00314     GLIBHashNode<Key> *Node, *Previous;
00315     unsigned int Deleted = 0;
00316 
00317     for (int i = 0; i < m_Size; i++)
00318     {
00319     Restart:
00320         Previous = NULL;
00321   
00322         for (Node = m_Nodes[i]; Node; Previous = Node, Node = Node->m_Next)
00323         {
00324             if (RemoveFunc->ProcessHash(Node->m_Key, Node->m_Value, configData))
00325             {
00326                 Deleted += 1;
00327                 m_NumberOfElements -= 1;
00328 
00329                 if (Previous)
00330                 {
00331                     Previous->m_Next = Node->m_Next;
00332                     delete Node;
00333                     Node = Previous;
00334                 }
00335                 else
00336                 {
00337                     m_Nodes[i] = Node->m_Next;
00338                     delete Node;
00339                     goto Restart;
00340                 }
00341             }
00342         }
00343     }
00344 
00345     if (!m_Frozen)
00346         Resize();
00347 
00348     return Deleted;
00349 }
00350 
00351 template <class Key, class ConfigData>
00352 int GLIBHash<Key, ConfigData>::GetSize()
00353 {
00354     return m_NumberOfElements;
00355 }
00356 
00357 template <class Key, class ConfigData>
00358 GLIBHashNode<Key>** GLIBHash<Key, ConfigData>::LookupNode(Key* key)
00359 {
00360     GLIBHashNode<Key> **Node;
00361   
00362     Node = &m_Nodes[m_Hash->Hash(key) % m_Size];
00363   
00364     /* Hash table lookup needs to be fast.
00365      *  We therefore remove the extra conditional of testing
00366      *  whether to call the key_compare_func or not from
00367      *  the inner loop.
00368      */
00369     if (m_Compare)
00370         while (*Node && (m_Compare->Compare((*Node)->m_Key, key, NULL) != 0) )
00371             Node = &(*Node)->m_Next;
00372     else
00373         while (*Node && (*Node)->m_Key != key)
00374             Node = &(*Node)->m_Next;
00375 
00376     return Node;
00377 }
00378 
00379 #endif

Generated on Sat Nov 5 11:20:16 2005 for Cpp Freecell Solver by  doxygen 1.4.4