TCHashTable.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef TC_HASHTABLE_H
00037 #define TC_HASHTABLE_H
00038
00039 #include "TCTypes.h"
00040
00041 #include <vector>
00042 #include <string>
00043 #include <functional>
00044
00045 namespace TC
00046 {
00060 template <class KEY_TYPE> struct Hash { };
00061
00063 template<> struct Hash<sint8>
00064 {
00065 uint32 operator() (sint8 val) const { return val; }
00066 };
00068 template<> struct Hash<uint8>
00069 {
00070 uint32 operator() (uint8 val) const { return val; }
00071 };
00073 template<> struct Hash<sint16>
00074 {
00075 uint32 operator() (sint16 val) const { return val; }
00076 };
00078 template<> struct Hash<uint16>
00079 {
00080 uint32 operator() (uint16 val) const { return val; }
00081 };
00083 template<> struct Hash<sint32>
00084 {
00085 uint32 operator() (sint32 val) const { return val; }
00086 };
00088 template<> struct Hash<uint32>
00089 {
00090 uint32 operator() (uint32 val) const { return val; }
00091 };
00092
00094 template<> struct Hash<char*>
00095 {
00096 uint32 operator() (const char* text) const
00097 {
00098 const char *s = text;
00099 uint32 h=0;
00100 uint32 c;
00101 while((c=*s++) != '\0')
00102 {
00103 h = ((h << 5) + h) ^ c;
00104 }
00105 return h;
00106 }
00107 };
00108
00110 template<> struct Hash<std::string>
00111 {
00112 uint32 operator() (const std::string& text) const
00113 {
00114 const char *s = text.c_str();
00115 uint32 h=0;
00116 uint32 c;
00117 while((c=*s++) != '\0')
00118 {
00119 h = ((h << 5) + h) ^ c;
00120 }
00121 return h;
00122 }
00123 };
00124
00141 template< class KEY_TYPE,
00142 class MAP_TYPE=sint32,
00143 class HASH_FUNC=Hash< KEY_TYPE>,
00144 class KEY_VALUE_COMPARE_FUNC=std::equal_to<KEY_TYPE> >
00145 class HashTable
00146 {
00147 private:
00152 struct _Element
00153 {
00154 KEY_TYPE key_value;
00155 MAP_TYPE map_value;
00156 };
00157
00158 public:
00165 HashTable(uint32 size, const MAP_TYPE& notFound)
00166 :m_size(size),
00167 m_not_found(notFound)
00168 {
00169 Clear();
00170 }
00171
00173 virtual ~HashTable() {}
00174
00176 inline uint32 GetHashSize() const { return m_size; }
00177
00182 inline void SetHashSize(uint32 size)
00183 {
00184 m_size = size;
00185 Clear();
00186 }
00187
00192 inline void Clear()
00193 {
00194 m_data.clear();
00195 m_data.reserve(m_size);
00196 for (uint32 i=0; i<m_size; i++)
00197 {
00198 m_data.push_back(std::vector< _Element >());
00199 }
00200 }
00201
00206 inline const MAP_TYPE& GetNotFoundValue() const { return m_not_found; }
00207
00212 inline void SetNotFoundValue(const MAP_TYPE& notFound) { m_not_found = notFound; }
00213
00220 void AddKey(const KEY_TYPE &key_value, const MAP_TYPE& map_value)
00221 {
00222 uint32 p1;
00223 sint32 p2;
00224 GetElementPosition(key_value, p1, p2);
00225
00226 _Element elem;
00227 elem.key_value = key_value;
00228 elem.map_value = map_value;
00229 if (p2 == -1)
00230 {
00231 m_data[p1].push_back(elem);
00232 }
00233 else
00234 {
00235 m_data[p1][p2] = elem;
00236 }
00237 }
00238
00246 void RemoveKey(const KEY_TYPE &key_value)
00247 {
00248 uint32 p1;
00249 sint32 p2;
00250 GetElementPosition(key_value, p1, p2);
00251
00252
00253 if (p2 != -1)
00254 {
00255 m_data[p1].erase(m_data[p1].begin() + p2);
00256 }
00257 }
00258
00266 const MAP_TYPE& GetMappedValue(const KEY_TYPE& key_value) const
00267 {
00268 uint32 p1;
00269 sint32 p2;
00270 GetElementPosition(key_value, p1, p2);
00271
00272 if (p2 == -1)
00273 {
00274 return m_not_found;
00275 }
00276 else
00277 {
00278 return m_data[p1][p2].map_value;
00279 }
00280 }
00281
00283 const MAP_TYPE& operator[](const KEY_TYPE& key_value) const { return GetMappedValue(key_value);}
00284
00286 void GetAllKeys(std::vector< KEY_TYPE >& keys)
00287 {
00288 for (uint32 i=0; i<m_data.size(); i++)
00289 {
00290 for (uint32 j=0; j<m_data[i].size(); j++)
00291 {
00292 keys.push_back(m_data[i][j].key_value);
00293 }
00294 }
00295 }
00296
00298 void GetAllKeysAndValues(std::vector< KEY_TYPE >& keys, std::vector< MAP_TYPE >& values)
00299 {
00300 for (uint32 i=0; i<m_data.size(); i++)
00301 {
00302 for (uint32 j=0; j<m_data[i].size(); j++)
00303 {
00304 keys.push_back(m_data[i][j].key_value);
00305 values.push_back(m_data[i][j].map_value);
00306 }
00307 }
00308 }
00309
00316 void GetStatistics(uint32& numEmptyLists, uint32& maxListLength, double& avgListLength) const
00317 {
00318 numEmptyLists = 0;
00319 maxListLength = 0;
00320 avgListLength = 0;
00321 for (uint32 i = 0; i < m_data.size(); i++)
00322 {
00323 uint32 thisListLength = m_data[i].size();
00324 if (thisListLength == 0) numEmptyLists++;
00325 if (maxListLength < thisListLength) maxListLength = thisListLength;
00326 avgListLength += thisListLength;
00327 }
00328 avgListLength /= m_data.size();
00329 }
00330
00331 private:
00338 void GetElementPosition(const KEY_TYPE &key_value, uint32 &p1, sint32 &p2) const
00339 {
00340 KEY_VALUE_COMPARE_FUNC compare;
00341 p1 = GetTableEntryPosition(key_value);
00342 p2 = -1;
00343 for (uint32 i=0; i<m_data[p1].size(); i++)
00344 {
00345 if (compare(m_data[p1][i].key_value, key_value))
00346 {
00347 p2 = i;
00348 break;
00349 }
00350 }
00351 }
00352
00361 uint32 GetTableEntryPosition(const KEY_TYPE &key_value) const
00362 {
00363 HASH_FUNC func;
00364 return (func(key_value) % m_size);
00365 }
00366
00367 private:
00369 uint32 m_size;
00371 MAP_TYPE m_not_found;
00373 std::vector< std::vector< _Element > > m_data;
00374 };
00375
00379 }
00380
00381 #endif // TC_HASHTABLE_H