12#ifndef TT_INCLUDE__HASHTEMPLATECLASS_H
13#define TT_INCLUDE__HASHTEMPLATECLASS_H
17#include "HashTemplateKeyClass.h"
18#include "engine_math.h"
21template<
typename Key,
typename Value>
class HashTemplateIterator;
25template<
typename Key,
typename Value>
class HashTemplateClass
30 friend HashTemplateIterator<Key, Value>;
46 static uint computeHash(
const Key& key, uint maxHashCount)
48 TT_ASSERT(isPowerOfTwo(maxHashCount));
49 return HashTemplateKeyClass<Key>::Get_Hash_Value(key) & (maxHashCount - 1);
54 uint computeHash(
const Key& key)
const
56 return computeHash(key, maxHashCount);
63 uint newMaxHashCount = max(maxHashCount * 2, 4);
65 Entry* newEntries =
new Entry[newMaxHashCount];
66 int* newIndices =
new int[newMaxHashCount];
69 for (uint index = 0; index < newMaxHashCount; index++)
70 newIndices[index] = -1;
72 for (uint hash = 0; hash < maxHashCount; hash++)
74 for (
int index = indices[hash]; index != -1; index = entries[index].next)
76 uint hash2 = computeHash(entries[index].key, newMaxHashCount);
78 newEntries[unusedEntryIndex].next = newIndices[hash2];
79 newEntries[unusedEntryIndex].key = entries[index].key;
80 newEntries[unusedEntryIndex].value = entries[index].value;
82 newIndices[hash2] = unusedEntryIndex;
90 for (uint i = unusedEntryIndex; i < newMaxHashCount-1; i++)
91 newEntries[i].next = i + 1;
93 newEntries[newMaxHashCount-1].next = -1;
97 maxHashCount = newMaxHashCount;
110 unusedEntryIndex = -1;
116 HashTemplateClass(
const HashTemplateClass& o) : unusedEntryIndex(o.unusedEntryIndex), maxHashCount(o.maxHashCount)
120 indices =
new int[o.maxHashCount];
121 memcpy(indices, o.indices,
sizeof(
int) * o.maxHashCount);
130 entries =
new Entry[o.maxHashCount];
131 memcpy(entries, o.entries,
sizeof(Entry) * o.maxHashCount);
140 HashTemplateClass& operator= (
const HashTemplateClass& o)
147 unusedEntryIndex = o.unusedEntryIndex;
148 maxHashCount = o.maxHashCount;
152 indices =
new int[o.maxHashCount];
153 memcpy(indices, o.indices,
sizeof(
int) * o.maxHashCount);
162 entries =
new Entry[o.maxHashCount];
163 memcpy(entries, o.entries,
sizeof(Entry) * o.maxHashCount);
182 Value* Get(
const Key& key)
const
185 for (uint index = indices[computeHash(key)]; index != -1; index = entries[index].next)
186 if (entries[index].key == key)
187 return &entries[index].value;
194 Value Get(
const Key& key, Value
default)
const
196 Value* result = Get(key);
197 return result ? *result :
default;
202 bool Exists(
const Key& key)
const
204 return Get(key) != NULL;
209 void Insert(
const Key& key,
const Value& value)
212 if (unusedEntryIndex == -1)
215 uint index = unusedEntryIndex;
216 unusedEntryIndex = entries[index].next;
218 uint hash = computeHash(key);
219 entries[index].key = key;
220 entries[index].value = value;
221 entries[index].next = indices[hash];
222 indices[hash] = index;
227 void Remove(
const Key& key)
231 uint hash = computeHash(key);
232 int* lastEntryNext = &indices[hash];
234 for (uint index = indices[hash]; index != -1; index = entries[index].next)
236 Entry& entry = entries[index];
237 if (entry.key == key)
239 *lastEntryNext = entry.next;
240 entries[index].next = unusedEntryIndex;
241 unusedEntryIndex = index;
246 lastEntryNext = &entries[index].next;
254 void Remove(
const Key& key,
const Value& value)
258 uint hash = computeHash(key);
259 int* lastEntryNext = &indices[hash];
261 for (uint index = indices[hash]; index != -1; index = entries[index].next)
263 Entry& entry = entries[index];
264 if (entry.key == key && entry.value == value)
266 *lastEntryNext = entry.next;
267 entries[index].next = unusedEntryIndex;
268 unusedEntryIndex = index;
273 lastEntryNext = &entries[index].next;
282 for (uint hash = 0; hash < maxHashCount; hash++)
284 uint index = indices[hash];
287 uint lastHash = index;
288 while (entries[lastHash].next != -1)
289 lastHash = entries[lastHash].next;
291 entries[lastHash].next = unusedEntryIndex;
292 unusedEntryIndex = index;
300 uint Get_Size()
const
304 for (uint hash = 0; hash < maxHashCount; hash++)
306 uint index = indices[hash];
310 index = entries[index].next;
317 const Value getValueByIndex(
int index)
const
319 Value value = entries[index].value;
325 for (uint hash = 0; hash < maxHashCount; hash++)
327 uint index = indices[hash];
330 TT_ASSERT(computeHash(entries[index].key) == hash);
331 index = entries[index].next;
340 HashTemplateClass<uint, uint> table;
342 for (uint run = 0; run < 10; run++)
345 for (uint i = 0; i < 1234; i++)
347 bits[i] = rand() > (RAND_MAX & 1);
349 table.Insert(i*45, i*2+5678);
352 for (uint i = 0; i < 1234; i++)
354 TT_ASSERT(bits[i] == table.Exists(i*45));
356 TT_ASSERT(*table.Get(i*45) == i*2+5678);
359 for (uint i = 0; i < 1234/2; i++)
361 if (rand() > (RAND_MAX & 1))
365 table.Insert(i*45, i*2+5678);
371 for (uint i = 0; i < 1234; i++)
373 TT_ASSERT(bits[i] == table.Exists(i*45));
375 TT_ASSERT(*table.Get(i*45) == i*2+5678);
380 for (uint i = 0; i < 1234; i++)
381 TT_ASSERT(table.Exists(i*45) ==
false);