added COMPARATOR to HashTable

This commit is contained in:
hyung-hwan 2015-02-05 16:13:33 +00:00
parent 6da46ff4e1
commit 0a5ee4de4d

View File

@ -44,6 +44,15 @@ struct HashTableHasher
} }
}; };
template<typename T>
struct HashTableComparator
{
bool operator() (const T& v1, const T& v2) const
{
return v1 == v2;
}
};
struct HashTableResizer struct HashTableResizer
{ {
qse_size_t operator() (qse_size_t current) const qse_size_t operator() (qse_size_t current) const
@ -56,13 +65,13 @@ struct HashTableResizer
} }
}; };
template <typename K, typename V, typename HASHER = HashTableHasher<K>, typename RESIZER = HashTableResizer> template <typename K, typename V, typename HASHER = HashTableHasher<K>, typename COMPARATOR = HashTableComparator<K>, typename RESIZER = HashTableResizer>
class HashTable: public Mmged class HashTable: public Mmged
{ {
public: public:
typedef Pair<K,V> Entry; typedef Pair<K,V> Entry;
typedef LinkedList<Entry> Bucket; typedef LinkedList<Entry> Bucket;
typedef HashTable<K,V,HASHER,RESIZER> SelfType; typedef HashTable<K,V,HASHER,COMPARATOR,RESIZER> SelfType;
protected: protected:
Bucket** allocate_bucket (Mmgr* mm, qse_size_t bs) const Bucket** allocate_bucket (Mmgr* mm, qse_size_t bs) const
@ -205,7 +214,7 @@ public:
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Entry& e = np->value;
if (key == e.key) return e.value; if (this->comparator (key, e.key)) return e.value;
} }
if (entry_count >= threshold) if (entry_count >= threshold)
@ -214,6 +223,7 @@ public:
hc = this->hasher(key) % bucket_size; hc = this->hasher(key) % bucket_size;
} }
// insert a new key if the key is not found
Entry& e2 = this->buckets[hc]->append (Entry(key)); Entry& e2 = this->buckets[hc]->append (Entry(key));
entry_count++; entry_count++;
return e2.value; return e2.value;
@ -223,22 +233,13 @@ public:
{ {
qse_size_t hc = this->hasher(key) % this->bucket_size; qse_size_t hc = this->hasher(key) % this->bucket_size;
typename Bucket::Node* np; Entry* pair = this->find_pair (key, hc);
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) if (pair) return pair->value;
{
Entry& e = np->value;
if (key == e.key) return e.value;
}
if (entry_count >= threshold) // insert a new key if the key is not found
{ Entry& new_pair = this->buckets[hc]->append (Entry(key));
this->rehash (); this->entry_count++;
hc = this->hasher(key) % bucket_size; return new_pair.value;
}
Entry& e2 = this->buckets[hc]->append (Entry(key));
entry_count++;
return e2.value;
} }
#endif #endif
@ -280,15 +281,15 @@ public:
} }
protected: protected:
Entry* find_pair (const K& key) Entry* find_pair (const K& key, qse_size_t hc)
{ {
qse_size_t hc = this->hasher(key) % bucket_size; //qse_size_t hc = this->hasher(key) % this->bucket_size;
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Entry& e = np->value;
if (key == e.key) return &e; if (this->comparator (key, e.key)) return &e;
} }
return QSE_NULL; return QSE_NULL;
@ -297,12 +298,12 @@ protected:
public: public:
Entry* findPair (const K& key) Entry* findPair (const K& key)
{ {
return this->find_pair (key); return this->find_pair (key, this->hasher(key) % this->bucket_size);
} }
const Entry* findPair (const K& key) const const Entry* findPair (const K& key) const
{ {
return this->find_pair (key); return this->find_pair (key, this->hasher(key) % this->bucket_size);
} }
V* findValue (const K& key) V* findValue (const K& key)
@ -327,7 +328,7 @@ public:
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Entry& e = np->value;
if (key == e.key) if (this->comparator (key, e.key))
{ {
*hash_code = hc; *hash_code = hc;
*node = np; *node = np;
@ -346,7 +347,7 @@ public:
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Entry& e = np->value;
if (key == e.key) if (this->comparator (key, e.key))
{ {
*hash_code = hc; *hash_code = hc;
*node = np; *node = np;
@ -368,7 +369,7 @@ public:
return (insertNew(key,value) == QSE_NULL)? -1: 0; return (insertNew(key,value) == QSE_NULL)? -1: 0;
} }
V* insert (const K& key) Entry* insert (const K& key)
{ {
qse_size_t hc = this->hasher(key) % bucket_size; qse_size_t hc = this->hasher(key) % bucket_size;
@ -376,7 +377,7 @@ public:
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Entry& e = np->value;
if (key == e.key) return &e.value; if (this->comparator (key, e.key)) return &e;
} }
if (entry_count >= threshold) if (entry_count >= threshold)
@ -386,11 +387,11 @@ public:
} }
Entry& e = this->buckets[hc]->append (Entry(key)); Entry& e = this->buckets[hc]->append (Entry(key));
entry_count++; this->entry_count++;
return &e.value; return &e;
} }
V* insert (const K& key, const V& value) Entry* insert (const K& key, const V& value)
{ {
qse_size_t hc = this->hasher(key) % bucket_size; qse_size_t hc = this->hasher(key) % bucket_size;
@ -398,7 +399,7 @@ public:
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Entry& e = np->value;
if (key == e.key) return &e.value; if (this->comparator (key, e.key)) return &e;
} }
if (entry_count >= threshold) if (entry_count >= threshold)
@ -409,9 +410,84 @@ public:
Entry& e = this->buckets[hc]->append (Entry(key,value)); Entry& e = this->buckets[hc]->append (Entry(key,value));
entry_count++; entry_count++;
return &e.value; return &e;
} }
#if 0
Entry* upsert (const K& Key)
{
qse_size_t hc = this->hasher(key) % this->bucket_size;
Entry* pair = this->find_pair (key, hc);
if (pair)
{
// don't change the existing value.
return pair
}
if (entry_count >= threshold)
{
this->rehash ();
hc = this->hasher(key) % this->bucket_size;
}
// insert a new key if the key is not found
Entry& new_pair = this->buckets[hc]->append (Entry(key));
this->entry_count++;
return &new_pair
}
#endif
Entry* upsert (const K& key, const V& value)
{
qse_size_t hc = this->hasher(key) % this->bucket_size;
Entry* pair = this->find_pair (key, hc);
if (pair)
{
pair->value = value;
return pair;
}
if (entry_count >= threshold)
{
this->rehash ();
hc = this->hasher(key) % this->bucket_size;
}
// insert a new key if the key is not found
Entry& new_pair = this->buckets[hc]->append (Entry(key,value));
this->entry_count++;
return &new_pair;
/*
qse_size_t hc = this->hasher(key) % this->bucket_size;
typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{
Entry& e = np->value;
if (key == e.key)
{
e.value = value;
return &e.value;
}
}
if (entry_count >= threshold)
{
this->rehash ();
hc = this->hasher(key) % bucket_size;
}
Entry& e = this->buckets[hc]->append (Entry(key,value));
this->entry_count++;
return &e.value;
*/
}
#if 0
V* insertNew (const K& key) V* insertNew (const K& key)
{ {
qse_size_t hc = this->hasher(key) % bucket_size; qse_size_t hc = this->hasher(key) % bucket_size;
@ -455,32 +531,8 @@ public:
entry_count++; entry_count++;
return &e.value; return &e.value;
} }
#endif
V* upsert (const K& key, const V& value)
{
qse_size_t hc = this->hasher(key) % bucket_size;
typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{
Entry& e = np->value;
if (key == e.key)
{
e.value = value;
return &e.value;
}
}
if (entry_count >= threshold)
{
this->rehash ();
hc = this->hasher(key) % bucket_size;
}
Entry& e = this->buckets[hc]->append (Entry(key,value));
entry_count++;
return &e.value;
}
template <typename MK, typename MHASHER> template <typename MK, typename MHASHER>
int removeWithCustomKey (const MK& key) int removeWithCustomKey (const MK& key)
@ -646,6 +698,7 @@ protected:
mutable qse_size_t threshold; mutable qse_size_t threshold;
qse_size_t load_factor; qse_size_t load_factor;
HASHER hasher; HASHER hasher;
COMPARATOR comparator;
RESIZER resizer; RESIZER resizer;
void rehash () const void rehash () const