Go to the documentation of this file.00001
00002
00003
00004
00005
00006 #ifndef SG_HASHTABLE_H
00007 #define SG_HASHTABLE_H
00008
00009 #include "SgHash.h"
00010 #include "SgWrite.h"
00011
00012
00013
00014
00015 template <class DATA>
00016 struct SgHashEntry
00017 {
00018 SgHashEntry()
00019 : m_hash(),
00020 m_data()
00021 { }
00022
00023 SgHashEntry(const SgHashCode& code, const DATA& data)
00024 : m_hash(code),
00025 m_data(data)
00026 { }
00027
00028 SgHashCode m_hash;
00029
00030 DATA m_data;
00031 };
00032
00033
00034
00035
00036 template <class DATA>
00037 class SgHashTable
00038 {
00039 public:
00040
00041 explicit SgHashTable(int maxHash);
00042
00043 ~SgHashTable();
00044
00045
00046
00047
00048 void Age();
00049
00050
00051 void Clear();
00052
00053
00054
00055 bool Lookup(const SgHashCode& code, DATA* data) const;
00056
00057
00058 int MaxHash() const;
00059
00060
00061
00062
00063 bool Store(const SgHashCode& code, const DATA& data);
00064
00065
00066 int NuCollisions() const
00067 {
00068 return m_nuCollisions;
00069 }
00070
00071
00072 int NuStores() const
00073 {
00074 return m_nuStores;
00075 }
00076
00077
00078 int NuLookups() const
00079 {
00080 return m_nuLookups;
00081 }
00082
00083
00084 int NuFound() const
00085 {
00086 return m_nuFound;
00087 }
00088
00089 private:
00090
00091 SgHashEntry<DATA>* m_entry;
00092
00093
00094 int m_maxHash;
00095
00096
00097
00098
00099
00100 mutable int m_nuCollisions;
00101
00102
00103 mutable int m_nuStores;
00104
00105
00106 mutable int m_nuLookups;
00107
00108
00109 mutable int m_nuFound;
00110
00111
00112 SgHashTable(const SgHashTable&);
00113
00114
00115 SgHashTable& operator=(const SgHashTable&);
00116 };
00117
00118 template <class DATA>
00119 SgHashTable<DATA>::SgHashTable(int maxHash)
00120 : m_entry(0),
00121 m_maxHash(maxHash),
00122 m_nuCollisions(0),
00123 m_nuStores(0),
00124 m_nuLookups(0),
00125 m_nuFound(0)
00126 {
00127 m_entry = new SgHashEntry<DATA>[m_maxHash];
00128 Clear();
00129 }
00130
00131 template <class DATA>
00132 SgHashTable<DATA>::~SgHashTable()
00133 {
00134 delete[] m_entry;
00135 }
00136
00137 template <class DATA>
00138 void SgHashTable<DATA>::Age()
00139 {
00140 for (int i = m_maxHash-1; i >= 0; --i)
00141 {
00142 m_entry[i].m_data.AgeData();
00143 }
00144 }
00145
00146 template <class DATA>
00147 void SgHashTable<DATA>::Clear()
00148 {
00149 for (int i = m_maxHash-1; i >= 0; --i)
00150 {
00151 m_entry[i].m_data.Invalidate();
00152 }
00153 }
00154
00155 template <class DATA>
00156 int SgHashTable<DATA>::MaxHash() const
00157 {
00158 return m_maxHash;
00159 }
00160
00161 template <class DATA>
00162 bool SgHashTable<DATA>::Store(const SgHashCode& code, const DATA& data)
00163 {
00164 ++m_nuStores;
00165 int h = code.Hash(m_maxHash);
00166 SgHashEntry<DATA>& entry = m_entry[h];
00167 if (entry.m_data.IsValid() && code != entry.m_hash)
00168 ++m_nuCollisions;
00169 if (! entry.m_data.IsValid() || data.IsBetterThan(entry.m_data))
00170 {
00171 entry.m_hash = code;
00172 entry.m_data = data;
00173 return true;
00174 }
00175 return false;
00176 }
00177
00178 template <class DATA>
00179 bool SgHashTable<DATA>::Lookup(const SgHashCode& code, DATA* data) const
00180 {
00181 ++m_nuLookups;
00182 int h = code.Hash(m_maxHash);
00183 const SgHashEntry<DATA>& entry = m_entry[h];
00184 if (entry.m_data.IsValid() && entry.m_hash == code)
00185 {
00186 *data = entry.m_data;
00187 ++m_nuFound;
00188 return true;
00189 }
00190 return false;
00191 }
00192
00193
00194
00195
00196 template <class DATA>
00197 std::ostream& operator<<(std::ostream& out, const SgHashTable<DATA>& hash)
00198 {
00199 out << "HashTableStatistics:\n"
00200 << SgWriteLabel("Stores") << hash.NuStores() << '\n'
00201 << SgWriteLabel("LookupAttempt") << hash.NuLookups() << '\n'
00202 << SgWriteLabel("LookupSuccess") << hash.NuFound() << '\n'
00203 << SgWriteLabel("Collisions") << hash.NuCollisions() << '\n';
00204 return out;
00205 }
00206
00207 #endif // SG_HASHTABLE_H