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

FCInternalHash.h

Go to the documentation of this file.
00001 #ifndef MMANN_FCINTERNAL_HASH_H
00002 #define MMANN_FCINTERNAL_HASH_H
00003 
00011 
00012 #include <assert.h>
00013 #include "AGenericHash.h"
00014 
00019 template <class Key>
00020 class FCHashItem
00021 {
00022 public:
00023 
00025     FCHashItem(Key* key, int value, FCHashItem<Key>* Next = NULL);
00026 
00028     Key* m_Key;
00029 
00031     int m_Value;
00032 
00034     FCHashItem<Key>* m_Next;
00035 };
00036 
00037 template <class Key>
00038 FCHashItem<Key>::FCHashItem(Key* key, int value, FCHashItem<Key>* Next)
00039 {
00040     m_Key = key;
00041     m_Value = value;
00042     m_Next = Next;
00043 }
00044 
00049 template <class Key, class ConfigData>
00050 class FCInternalHash : public AGenericHash<Key, ConfigData>
00051 {
00052 
00053 public:
00055     FCInternalHash(int SizeWanted, ACompareNodesAlgorithm<Key, ConfigData>* CompareAlgorithm,
00056                    AHashAlgorithm<Key>* Hash,
00057                    DeleteHashDataEnum DeleteHashData = NO_DELETE_HASH_ITEM);
00058 
00060     virtual ~FCInternalHash();
00061 
00067     Key* Insert(Key* key, bool OptimizeForCaching);
00068 
00070     virtual void DeleteItems();
00071 
00072 protected:
00076     void Rehash(FCInternalHash<Key, ConfigData>* Hash);
00077 
00081     virtual void Copy(AGenericHash<Key, ConfigData>* Hash);
00082 
00083 private:
00085     FCHashItem<Key>**   m_Entries;
00086 };
00087 
00088 template <class Key, class ConfigData>
00089 FCInternalHash<Key, ConfigData>::FCInternalHash(int SizeWanted, ACompareNodesAlgorithm<Key, ConfigData>* CompareAlgorithm,
00090                                                       AHashAlgorithm<Key>* Hash,
00091                                                       DeleteHashDataEnum DeleteHashData) : AGenericHash<Key, ConfigData>(SizeWanted, CompareAlgorithm, Hash, DeleteHashData)
00092 {
00093     // Find a prime number that is greater than the initial wanted size
00094     m_Size = FindClosestPrime(SizeWanted);
00095 
00096     // Allocate a table of size entries
00097     m_Entries = new FCHashItem<Key>*[m_Size];
00098 
00099     // Initialize all the cells of the hash table to NULL, which indicate
00100     // that the cork of the linked list is right at the start
00101     memset(m_Entries, 0, sizeof(FCHashItem<Key>*)*m_Size);
00102 }
00103 
00104 template <class Key, class ConfigData>
00105 FCInternalHash<Key, ConfigData>::~FCInternalHash()
00106 {
00107 }
00108 
00109 template <class Key, class ConfigData>
00110 void FCInternalHash<Key, ConfigData>::DeleteItems()
00111 {
00112     FCHashItem<Key> *Item, *NextItem;
00113 
00114     for(int i=0;i<m_Size;i++)
00115     {
00116         Item = m_Entries[i];
00117         while (Item != NULL)
00118         {
00119             NextItem = Item->m_Next;
00120             switch(m_DeleteHashData)
00121             {
00122             case NO_DELETE_HASH_ITEM:
00123                 break;
00124             case DELETE_HASH_ITEM:
00125                 delete Item->m_Key;
00126                 break;
00127             case DELETE_HASH_ITEM_ARRAY:
00128                 delete [] Item->m_Key;
00129                 break;
00130             default:
00131                 //This shouldn't happen
00132                 assert(false);
00133             }
00134             delete Item;
00135             Item = NextItem;
00136         }
00137     }
00138 
00139     delete [] m_Entries;
00140 }
00141 
00142 
00143 template <class Key, class ConfigData>
00144 Key* FCInternalHash<Key, ConfigData>::Insert(Key* key, bool OptimizeForCaching)
00145 {   
00146     FCHashItem<Key> *Item, *LastItem;
00147     int Value = m_Hash->Hash(key);
00148 
00149     // Get the index of the appropriate chain in the hash table
00150     FCHashItem<Key> **List = &m_Entries[Value % m_Size];
00151 
00152     // If first_item is non-existent
00153     if ((*List) == NULL)
00154     {
00155         // Allocate a first item with that key
00156         Item = (*List) = new FCHashItem<Key>(key, Value);
00157         goto RehashCheck;
00158     }
00159 
00160     // Initialize item to the chain's first_item
00161     Item = (*List);
00162     LastItem = NULL;
00163 
00164     while (Item != NULL)
00165     {
00166         // We first compare the hash values, because it is faster than
00167         // comparing the entire data structure.
00168 
00169 //      printf("Item->m_Value: %d\tValue: %d\tCompareValue: %d\n", Item->m_Value, Value, m_Compare->Compare(Item->m_Key, key, NULL));
00170         if ( (Item->m_Value == Value) && (m_Compare->Compare(Item->m_Key, key, NULL) == 0) )
00171         {
00172             if (OptimizeForCaching)
00173             {
00174                 // Place the item in the beginning of the chain.
00175                 // If last_item == NULL it is already the first item so leave
00176                 // it alone
00177                 if (LastItem != NULL)
00178                 {
00179                     LastItem->m_Next = Item->m_Next;
00180                     Item->m_Next = (*List);
00181                     (*List) = Item;
00182                 }
00183             }
00184             
00185             return Item->m_Key;
00186         }
00187 
00188         // Cache the item before the current in last_item
00189         LastItem = Item;
00190         // Move to the next item
00191         Item = Item->m_Next;
00192     }
00193         
00194     if (OptimizeForCaching)
00195     {
00196         // Put the new element at the beginning of the list
00197         Item = new FCHashItem<Key>(key, Value, (*List));
00198         (*List) = Item;
00199     }
00200     else
00201     {
00202         // Put the new element at the end of the list
00203         Item = LastItem->m_Next = new FCHashItem<Key>(key, Value);
00204     }
00205 
00206 RehashCheck:
00207     m_NumberOfElements++;
00208 
00209     if (m_NumberOfElements > ((m_Size*3)>>2))
00210         Rehash(this);
00211 
00212     return NULL;
00213 }
00214 
00215 template <class Key, class ConfigData>
00216 void FCInternalHash<Key, ConfigData>::Rehash(FCInternalHash<Key, ConfigData>* Hash)
00217 {
00218     FCInternalHash<Key, ConfigData>* NewHash;
00219     FCHashItem<Key> *Item, *NextItem;
00220     int Place;
00221 
00222     // Allocate a new hash with hash_init()
00223     NewHash = new FCInternalHash<Key, ConfigData>(Hash->m_Size*2, Hash->m_Compare, Hash->m_Hash, m_DeleteHashData);
00224     NewHash->m_NumberOfElements = Hash->m_NumberOfElements;
00225    
00226     // Copy the items to the new hash and deallocate the old ones in the same time
00227     for(int i=0;i<Hash->m_Size;i++)
00228     {
00229         Item = Hash->m_Entries[i];
00230         // traverse the chain item by item
00231         while(Item != NULL)
00232         {
00233             // The place in the new hash table
00234             Place = Item->m_Value % NewHash->m_Size;
00235 
00236             // Store the next item in the linked list in a safe place,
00237             // so we can retrieve it after the assignment
00238             NextItem = Item->m_Next;
00239 
00240             // It is placed in front of the first element in the chain,
00241             // so it should link to it
00242             Item->m_Next = NewHash->m_Entries[Place];
00243 
00244             // Make it the first item in its chain
00245             NewHash->m_Entries[Place] = Item;
00246 
00247             // Move to the next item this one.
00248             Item = NextItem;
00249         }
00250     }
00251 
00252     // Free the entries of the old hash
00253     delete [] Hash->m_Entries;
00254 
00255     // Copy the new hash to the old one
00256     Hash->Copy(NewHash);
00257 
00258     delete NewHash;
00259 }
00260 
00261 template <class Key, class ConfigData>
00262 void FCInternalHash<Key, ConfigData>::Copy(AGenericHash<Key, ConfigData>* Hash)
00263 {
00264     //copy the parent data
00265     AGenericHash<Key, ConfigData>::Copy(Hash);
00266 
00267     m_Entries = ((FCInternalHash<Key, ConfigData>*)Hash)->m_Entries;
00268 }
00269 
00270 #endif

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