experimenting on a simpler HashTable implementation
This commit is contained in:
parent
37792be000
commit
f93f5e9704
@ -64,26 +64,49 @@ struct HashListResizer
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The HashList class provides a linked list where a data item can be accessed
|
||||||
|
/// using hashing. The accessor functions are similar to those of the HashTable
|
||||||
|
/// class whereas the data items are linked with each other in a linked list.
|
||||||
|
/// Extra hashing buckets maintain pointers to the first and the last node of
|
||||||
|
/// data items whose hash values are equal. Unlike the HashTable class that
|
||||||
|
/// maintains pairs of a key and a value, it stores a series of single items
|
||||||
|
/// whose key is distinuguished via the hashing function.
|
||||||
|
///
|
||||||
|
/// For the capacicity of X, it allocates (X * 2) node slots(this->nodes).
|
||||||
|
/// For a hash value of hc, this->nodes[hc * 2] points to the first node and
|
||||||
|
/// this->nodes[hc * 2 + 1] ponits to the last node.
|
||||||
|
|
||||||
template <typename T, typename MPOOL = Mpool, typename HASHER = HashListHasher<T>, typename COMPARATOR = HashListComparator<T>, typename RESIZER = HashListResizer >
|
template <typename T, typename MPOOL = Mpool, typename HASHER = HashListHasher<T>, typename COMPARATOR = HashListComparator<T>, typename RESIZER = HashListResizer >
|
||||||
class HashList: public Mmged
|
class HashList: public Mmged
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef LinkedList<T,MPOOL> DatumList;
|
typedef LinkedList<T,MPOOL> DatumList;
|
||||||
typedef typename DatumList::Node Node;
|
typedef typename DatumList::Node Node;
|
||||||
typedef HashList<T,MPOOL,HASHER,COMPARATOR> SelfType;
|
typedef typename DatumList::Iterator Iterator;
|
||||||
|
typedef typename DatumList::Visiter Visiter;
|
||||||
|
typedef HashList<T,MPOOL,HASHER,COMPARATOR,RESIZER> SelfType;
|
||||||
|
|
||||||
typedef HashListHasher<T> DefaultHasher;
|
typedef HashListHasher<T> DefaultHasher;
|
||||||
typedef HashListComparator<T> DefaultComparator;
|
typedef HashListComparator<T> DefaultComparator;
|
||||||
typedef HashListResizer DefaultResizer;
|
typedef HashListResizer DefaultResizer;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DEFAULT_CAPACITY = 10,
|
||||||
|
DEFAULT_LOAD_FACTOR = 75, // Load factor in percentage
|
||||||
|
|
||||||
|
MIN_CAPACITY = 1,
|
||||||
|
MIN_LOAD_FACTOR = 20
|
||||||
|
};
|
||||||
|
|
||||||
HashList (
|
HashList (
|
||||||
Mmgr* mmgr = QSE_NULL,
|
Mmgr* mmgr = QSE_NULL,
|
||||||
qse_size_t node_capacity = 10,
|
qse_size_t node_capacity = DEFAULT_CAPACITY,
|
||||||
qse_size_t load_factor = 75,
|
qse_size_t load_factor = DEFAULT_LOAD_FACTOR,
|
||||||
qse_size_t mpb_size = 0): Mmged(mmgr)
|
qse_size_t mpb_size = 0): Mmged(mmgr)
|
||||||
{
|
{
|
||||||
if (node_capacity <= 0) node_capacity = 1;
|
if (node_capacity < MIN_CAPACITY) node_capacity = MIN_CAPACITY;
|
||||||
if (load_factor < 20) load_factor = 20;
|
if (load_factor < MIN_LOAD_FACTOR) load_factor = MIN_LOAD_FACTOR;
|
||||||
|
|
||||||
this->nodes = QSE_NULL;
|
this->nodes = QSE_NULL;
|
||||||
this->node_capacity = 0;
|
this->node_capacity = 0;
|
||||||
@ -98,10 +121,6 @@ public:
|
|||||||
//this->nodes = new Node*[total_count];
|
//this->nodes = new Node*[total_count];
|
||||||
this->nodes = (Node**)this->getMmgr()->allocate (QSE_SIZEOF(Node*) * total_count);
|
this->nodes = (Node**)this->getMmgr()->allocate (QSE_SIZEOF(Node*) * total_count);
|
||||||
|
|
||||||
// NOTE: something wil go wrong if the memory manager doesn't raise an exception
|
|
||||||
// upon memory allocation failure. Make sure to use a memory allocation
|
|
||||||
// that raises an exception.
|
|
||||||
|
|
||||||
this->node_capacity = node_capacity;
|
this->node_capacity = node_capacity;
|
||||||
for (qse_size_t i = 0; i < total_count; i++)
|
for (qse_size_t i = 0; i < total_count; i++)
|
||||||
{
|
{
|
||||||
@ -447,6 +466,11 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void traverse (Visiter& visiter)
|
||||||
|
{
|
||||||
|
return this->datum_list->traverse (visiter);
|
||||||
|
}
|
||||||
|
|
||||||
qse_size_t getCapacity() const
|
qse_size_t getCapacity() const
|
||||||
{
|
{
|
||||||
return this->node_capacity;
|
return this->node_capacity;
|
||||||
@ -457,6 +481,31 @@ public:
|
|||||||
return this->datum_list->getSize();
|
return this->datum_list->getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The getIterator() function returns an interator.
|
||||||
|
///
|
||||||
|
/// \code
|
||||||
|
/// struct IntHasher
|
||||||
|
/// {
|
||||||
|
/// qse_size_t operator() (int v) { return v; }
|
||||||
|
/// };
|
||||||
|
/// typedef QSE::HashList<int,QSE::Mpool,IntHasher> IntList;
|
||||||
|
///
|
||||||
|
/// IntList hl;
|
||||||
|
/// IntList::Iterator it;
|
||||||
|
///
|
||||||
|
/// hl.insert (10);
|
||||||
|
/// hl.insert (150);
|
||||||
|
/// hl.insert (200);
|
||||||
|
/// for (it = hl.getIterator(); it.isLegit(); it++)
|
||||||
|
/// {
|
||||||
|
/// printf ("%d\n", *it);
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
Iterator getIterator (qse_size_t index = 0)
|
||||||
|
{
|
||||||
|
return this->datum_list->getIterator (index);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mutable qse_size_t node_capacity;
|
mutable qse_size_t node_capacity;
|
||||||
mutable Node** nodes;
|
mutable Node** nodes;
|
||||||
@ -577,7 +626,6 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
QSE_END_NAMESPACE(QSE)
|
QSE_END_NAMESPACE(QSE)
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
@ -27,9 +27,11 @@
|
|||||||
#ifndef _QSE_CMN_HASHTABLE_HPP_
|
#ifndef _QSE_CMN_HASHTABLE_HPP_
|
||||||
#define _QSE_CMN_HASHTABLE_HPP_
|
#define _QSE_CMN_HASHTABLE_HPP_
|
||||||
|
|
||||||
#include <qse/Hashable.hpp>
|
/*#include <qse/Hashable.hpp>
|
||||||
#include <qse/cmn/LinkedList.hpp>
|
#include <qse/cmn/LinkedList.hpp>*/
|
||||||
|
|
||||||
#include <qse/cmn/Couple.hpp>
|
#include <qse/cmn/Couple.hpp>
|
||||||
|
#include <qse/cmn/HashList.hpp>
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
QSE_BEGIN_NAMESPACE(QSE)
|
QSE_BEGIN_NAMESPACE(QSE)
|
||||||
@ -54,6 +56,7 @@ struct HashTableComparator
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
struct HashTableResizer
|
struct HashTableResizer
|
||||||
{
|
{
|
||||||
qse_size_t operator() (qse_size_t current) const
|
qse_size_t operator() (qse_size_t current) const
|
||||||
@ -65,7 +68,118 @@ struct HashTableResizer
|
|||||||
(current + (current / 16));
|
(current + (current / 16));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef HashListResizer HashTableResizer;
|
||||||
|
|
||||||
|
template <typename K, typename V, typename MPOOL = Mpool, typename HASHER = HashTableHasher<K>, typename COMPARATOR = HashTableComparator<K>, typename RESIZER = HashTableResizer>
|
||||||
|
class HashTable: public Mmged
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Couple<K,V> Pair;
|
||||||
|
typedef HashTable<K,V,MPOOL,HASHER,COMPARATOR,RESIZER> SelfType;
|
||||||
|
|
||||||
|
typedef HashTableHasher<K> DefaultHasher;
|
||||||
|
typedef HashTableComparator<K> DefaultComparator;
|
||||||
|
typedef HashTableResizer DefaultResizer;
|
||||||
|
|
||||||
|
|
||||||
|
struct PairHasher
|
||||||
|
{
|
||||||
|
qse_size_t operator() (const Pair& p)
|
||||||
|
{
|
||||||
|
HASHER hasher;
|
||||||
|
return hasher (p.key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PairComparator
|
||||||
|
{
|
||||||
|
qse_size_t operator() (const Pair& p1, const Pair& p2)
|
||||||
|
{
|
||||||
|
COMPARATOR comparator;
|
||||||
|
return comparator (p1.key, p2.key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef HashList<Pair,MPOOL,PairHasher,PairComparator,RESIZER> PairList;
|
||||||
|
typedef typename PairList::Node PairNode;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DEFAULT_CAPACITY = PairList::DEFAULT_CAPACITY,
|
||||||
|
DEFAULT_LOAD_FACTOR = PairList::DEFAULT_LOAD_FACTOR,
|
||||||
|
|
||||||
|
MIN_CAPACITY = PairList::MIN_CAPACITY,
|
||||||
|
MIN_LOAD_FACTOR = PairList::MIN_LOAD_FACTOR
|
||||||
|
};
|
||||||
|
|
||||||
|
HashTable (Mmgr* mmgr, qse_size_t capacity = DEFAULT_CAPACITY, qse_size_t load_factor = DEFAULT_LOAD_FACTOR, qse_size_t mpb_size = 0): Mmged(mmgr), pair_list (mmgr, capacity, load_factor, mpb_size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HashTable (const SelfType& table): Mmged (table), pair_list (table.pair_list)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType& operator= (const SelfType& table)
|
||||||
|
{
|
||||||
|
this->pair_list = table.pair_list;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair* insert (const K& key, const V& value)
|
||||||
|
{
|
||||||
|
PairNode* node = this->pair_list.insert (Pair(key, value));
|
||||||
|
if (!node) return QSE_NULL;
|
||||||
|
return &node->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair* upsert (const K& key, const V& value)
|
||||||
|
{
|
||||||
|
PairNode* node = this->pair_list.upsert (Pair(key, value));
|
||||||
|
if (!node) return QSE_NULL;
|
||||||
|
return &node->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair* update (const K& key, const V& value)
|
||||||
|
{
|
||||||
|
PairNode* node = this->pair_list.update (Pair(key, value));
|
||||||
|
if (!node) return QSE_NULL;
|
||||||
|
return &node->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair* search (const K& key)
|
||||||
|
{
|
||||||
|
// TODO: find with custom...
|
||||||
|
PairNode* node = this->pair_list.update (Pair(key));
|
||||||
|
if (!node) return QSE_NULL;
|
||||||
|
return &node->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remove (const K& key)
|
||||||
|
{
|
||||||
|
// TODO: use removeWithCustom....
|
||||||
|
return this->pair_list.remove (Pair(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void clear ()
|
||||||
|
{
|
||||||
|
// TODO: accept new capacity.
|
||||||
|
return this->pair_list.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_size_t getSize() const
|
||||||
|
{
|
||||||
|
return this->pair_list.getSize ();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PairList pair_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
template <typename K, typename V, typename HASHER = HashTableHasher<K>, typename COMPARATOR = HashTableComparator<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
|
||||||
{
|
{
|
||||||
@ -79,8 +193,101 @@ public:
|
|||||||
typedef HashTableComparator<K> DefaultComparator;
|
typedef HashTableComparator<K> DefaultComparator;
|
||||||
typedef HashTableResizer DefaultResizer;
|
typedef HashTableResizer DefaultResizer;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DEFAULT_CAPACITY = 10,
|
||||||
|
DEFAULT_LOAD_FACTOR = 75, // Load factor in percentage
|
||||||
|
|
||||||
|
MIN_CAPACITY = 1,
|
||||||
|
MIN_LOAD_FACTOR = 20
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
class Iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Iterator (): bucket_index(0), bucket_node(QSE_NULL) {}
|
||||||
|
Iterator (qse_size_t index, BucketNode* node): bucket_index(index), bucket_node(node) {}
|
||||||
|
Iterator (const Iterator& it): bucket_index (it.bucket_index), bucket_node(it.bucket_node) {}
|
||||||
|
|
||||||
|
Iterator& operator= (const Iterator& it)
|
||||||
|
{
|
||||||
|
this->bucket_index = it.bucket_index;
|
||||||
|
this->bucket_node = it.bucket_node;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator& operator++ () // prefix increment
|
||||||
|
{
|
||||||
|
QSE_ASSERT (this->isLegit());
|
||||||
|
this->bucket_node = this->bucket_node->getNext();
|
||||||
|
if (!this->bucket_node)
|
||||||
|
{
|
||||||
|
while (this->bucket_index
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator operator++ (int) // postfix increment
|
||||||
|
{
|
||||||
|
QSE_ASSERT (this->isLegit());
|
||||||
|
Iterator saved (*this);
|
||||||
|
this->current = this->current->getNext(); //++(*this);
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator& operator-- () // prefix decrement
|
||||||
|
{
|
||||||
|
QSE_ASSERT (this->isLegit());
|
||||||
|
this->current = this->current->getPrev();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator operator-- (int) // postfix decrement
|
||||||
|
{
|
||||||
|
QSE_ASSERT (this->isLegit());
|
||||||
|
Iterator saved (*this);
|
||||||
|
this->current = this->current->getPrev(); //--(*this);
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator== (const Iterator& it) const
|
||||||
|
{
|
||||||
|
return this->bucket_index == it.bucket_index &&
|
||||||
|
this->bucket_node == it.bucket_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!= (const Iterator& it) const
|
||||||
|
{
|
||||||
|
return this->bucket_index != it.bucket_index ||
|
||||||
|
this->bucket_node != it.bucket_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLegit () const
|
||||||
|
{
|
||||||
|
// TODO: change this
|
||||||
|
return this->bucket_node != QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator* () // dereference
|
||||||
|
{
|
||||||
|
return this->bucket_node->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator* () const // dereference
|
||||||
|
{
|
||||||
|
return this->bucket_node->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SelfType* table;
|
||||||
|
qse_size_t bucket_index;
|
||||||
|
BucketNode* bucket_node;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Bucket** allocate_bucket (Mmgr* mm, qse_size_t bs) const
|
Bucket** allocate_bucket (Mmgr* mm, qse_size_t bs, qse_size_t mpb_size) const
|
||||||
{
|
{
|
||||||
Bucket** b = QSE_NULL;
|
Bucket** b = QSE_NULL;
|
||||||
|
|
||||||
@ -89,7 +296,7 @@ protected:
|
|||||||
b = (Bucket**) mm->callocate (QSE_SIZEOF(*b) * bs);
|
b = (Bucket**) mm->callocate (QSE_SIZEOF(*b) * bs);
|
||||||
for (qse_size_t i = 0; i < bs; i++)
|
for (qse_size_t i = 0; i < bs; i++)
|
||||||
{
|
{
|
||||||
b[i] = new(mm) Bucket (mm, this->bucket_mpb_size);
|
b[i] = new(mm) Bucket (mm, mpb_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
@ -129,9 +336,12 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HashTable (Mmgr* mmgr, qse_size_t bucket_size = 10, qse_size_t load_factor = 75, qse_size_t bucket_mpb_size = 0): Mmged(mmgr)
|
HashTable (Mmgr* mmgr, qse_size_t bucket_size = DEFAULT_CAPACITY, qse_size_t load_factor = DEFAULT_LOAD_FACTOR, qse_size_t bucket_mpb_size = 0): Mmged(mmgr)
|
||||||
{
|
{
|
||||||
this->buckets = this->allocate_bucket (this->getMmgr(), bucket_size);
|
if (bucket_size < MIN_CAPACITY) bucket_size = MIN_CAPACITY;
|
||||||
|
if (load_factor < MIN_LOAD_FACTOR) load_factor = MIN_LOAD_FACTOR;
|
||||||
|
|
||||||
|
this->buckets = this->allocate_bucket (this->getMmgr(), bucket_size, bucket_mpb_size);
|
||||||
this->bucket_size = bucket_size;
|
this->bucket_size = bucket_size;
|
||||||
this->pair_count = 0;
|
this->pair_count = 0;
|
||||||
this->load_factor = load_factor;
|
this->load_factor = load_factor;
|
||||||
@ -141,7 +351,7 @@ public:
|
|||||||
|
|
||||||
HashTable (const SelfType& table): Mmged (table)
|
HashTable (const SelfType& table): Mmged (table)
|
||||||
{
|
{
|
||||||
this->buckets = this->allocate_bucket (this->getMmgr(), table.bucket_size);
|
this->buckets = this->allocate_bucket (this->getMmgr(), table.bucket_size, table.bucket_mpb_size);
|
||||||
this->bucket_size = table.bucket_size;
|
this->bucket_size = table.bucket_size;
|
||||||
this->pair_count = 0;
|
this->pair_count = 0;
|
||||||
this->load_factor = table.load_factor;
|
this->load_factor = table.load_factor;
|
||||||
@ -414,9 +624,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert a new pair
|
// insert a new pair
|
||||||
Pair& new_pair = this->buckets[hc]->append (Pair(key));
|
BucketNode* node = this->buckets[hc]->append (Pair(key));
|
||||||
this->pair_count++;
|
this->pair_count++;
|
||||||
return &new_pair;
|
return &node->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The insert() function inserts a new pair with a \a key with a \a value.
|
/// The insert() function inserts a new pair with a \a key with a \a value.
|
||||||
@ -436,9 +646,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert a new pair
|
// insert a new pair
|
||||||
Pair& new_pair = this->buckets[hc]->append (Pair(key, value));
|
BucketNode* node = this->buckets[hc]->append (Pair(key, value));
|
||||||
this->pair_count++;
|
this->pair_count++;
|
||||||
return &new_pair;
|
return &node->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The update() function updates an existing pair of the \a key
|
/// The update() function updates an existing pair of the \a key
|
||||||
@ -469,9 +679,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert a new pair if the key is not found
|
// insert a new pair if the key is not found
|
||||||
Pair& new_pair = this->buckets[hc]->append (Pair(key));
|
BucketNode* node = this->buckets[hc]->append (Pair(key));
|
||||||
this->pair_count++;
|
this->pair_count++;
|
||||||
return &new_pair;
|
return &node->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The upsert() function inserts a new pair with a \a key and a \a value
|
/// The upsert() function inserts a new pair with a \a key and a \a value
|
||||||
@ -496,9 +706,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert a new pair if the key is not found
|
// insert a new pair if the key is not found
|
||||||
Pair& new_pair = this->buckets[hc]->append (Pair(key, value));
|
BucketNode* node = this->buckets[hc]->append (Pair(key, value));
|
||||||
this->pair_count++;
|
this->pair_count++;
|
||||||
return &new_pair;
|
return &node->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -550,7 +760,7 @@ public:
|
|||||||
|
|
||||||
if (new_bucket_size > 0)
|
if (new_bucket_size > 0)
|
||||||
{
|
{
|
||||||
Bucket** tmp = this->allocate_bucket (this->getMmgr(), new_bucket_size);
|
Bucket** tmp = this->allocate_bucket (this->getMmgr(), new_bucket_size, this->bucket_mpb_size);
|
||||||
this->dispose_bucket (this->getMmgr(), this->buckets, this->bucket_size);
|
this->dispose_bucket (this->getMmgr(), this->buckets, this->bucket_size);
|
||||||
|
|
||||||
this->buckets = tmp;
|
this->buckets = tmp;
|
||||||
@ -595,6 +805,10 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Iterator getIterator ()
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mutable qse_size_t pair_count;
|
mutable qse_size_t pair_count;
|
||||||
mutable qse_size_t bucket_size;
|
mutable qse_size_t bucket_size;
|
||||||
@ -609,7 +823,7 @@ protected:
|
|||||||
void rehash () const
|
void rehash () const
|
||||||
{
|
{
|
||||||
qse_size_t new_bucket_size = this->resizer (this->bucket_size);
|
qse_size_t new_bucket_size = this->resizer (this->bucket_size);
|
||||||
Bucket** new_buckets = this->allocate_bucket (this->getMmgr(), new_bucket_size);
|
Bucket** new_buckets = this->allocate_bucket (this->getMmgr(), new_bucket_size, this->bucket_mpb_size);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -629,7 +843,9 @@ protected:
|
|||||||
// and retains the previous pointers before rehashing.
|
// and retains the previous pointers before rehashing.
|
||||||
// if the bucket uses a memory pool, this would not
|
// if the bucket uses a memory pool, this would not
|
||||||
// work. fortunately, the hash table doesn't use it
|
// work. fortunately, the hash table doesn't use it
|
||||||
// for a bucket.
|
// for a bucket. ---> this is not true any more.
|
||||||
|
// ---> this has been broken as memory pool
|
||||||
|
// ---> can be activated for buckets.
|
||||||
BucketNode* np = this->buckets[i]->getHeadNode();
|
BucketNode* np = this->buckets[i]->getHeadNode();
|
||||||
while (np)
|
while (np)
|
||||||
{
|
{
|
||||||
@ -654,6 +870,7 @@ protected:
|
|||||||
this->threshold = this->load_factor * this->bucket_size / 100;
|
this->threshold = this->load_factor * this->bucket_size / 100;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
QSE_END_NAMESPACE(QSE)
|
QSE_END_NAMESPACE(QSE)
|
||||||
|
@ -138,7 +138,7 @@ public:
|
|||||||
return this->current != it.current;
|
return this->current != it.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValid () const
|
bool isLegit () const
|
||||||
{
|
{
|
||||||
return this->current != QSE_NULL;
|
return this->current != QSE_NULL;
|
||||||
}
|
}
|
||||||
@ -211,6 +211,13 @@ public:
|
|||||||
typedef Mpool DefaultMpool;
|
typedef Mpool DefaultMpool;
|
||||||
typedef LinkedListComparator<T> DefaultComparator;
|
typedef LinkedListComparator<T> DefaultComparator;
|
||||||
|
|
||||||
|
struct Visiter
|
||||||
|
{
|
||||||
|
// return 1 to move forward, -1 to move backward, 0 to stop
|
||||||
|
virtual ~Visiter() {}
|
||||||
|
virtual int operator() (Node* node) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
INVALID_INDEX = ~(qse_size_t)0
|
INVALID_INDEX = ~(qse_size_t)0
|
||||||
@ -315,6 +322,20 @@ public:
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The prependNode() function adds an externally created \a node
|
||||||
|
/// to the front of the list.
|
||||||
|
Node* prependNode (Node* node)
|
||||||
|
{
|
||||||
|
return this->insertNode (this->head_node, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The appendNode() function adds an externally created \a node
|
||||||
|
/// to the back of the list.
|
||||||
|
Node* appendNode (Node* node)
|
||||||
|
{
|
||||||
|
return this->insertNode (QSE_NULL, node);
|
||||||
|
}
|
||||||
|
|
||||||
// create a new node to hold the value and insert it.
|
// create a new node to hold the value and insert it.
|
||||||
Node* insert (Node* pos, const T& value)
|
Node* insert (Node* pos, const T& value)
|
||||||
{
|
{
|
||||||
@ -643,6 +664,24 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void traverse (Visiter& visiter)
|
||||||
|
{
|
||||||
|
Node* cur, * prev, * next;
|
||||||
|
|
||||||
|
cur = this->head_node;
|
||||||
|
while (cur)
|
||||||
|
{
|
||||||
|
prev = cur->prev;
|
||||||
|
next = cur->next;
|
||||||
|
|
||||||
|
int n = visiter (cur);
|
||||||
|
|
||||||
|
if (n > 0) cur = next;
|
||||||
|
else if (n < 0) cur = prev;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Iterator getIterator (qse_size_t index = 0) const
|
Iterator getIterator (qse_size_t index = 0) const
|
||||||
{
|
{
|
||||||
if (this->node_count <= 0)
|
if (this->node_count <= 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user