35 # include <hash-dry.H> 37 # include <hash-fct.H> 42 using namespace Aleph;
72 template <
typename Key,
class Cmp = Aleph::equal_to<Key>>
74 :
public OhashCommon<OLhashTable<Key, Cmp>, Key>,
79 public StlAlephIterator<OLhashTable<Key, Cmp>>
81 friend class OhashCommon<OLhashTable<Key, Cmp>, Key>;
87 using Item_Type = Key;
89 using Hash_Fct = std::function<size_t(const Key &)>;
91 using Hash_Fct_Ptr = size_t (*) (
const Key&);
93 enum Status { EMPTY, BUSY, DELETED };
100 Bucket() noexcept : status(EMPTY) {}
101 void reset() noexcept { status = EMPTY; }
104 static Bucket * key_to_bucket(Key * rec) noexcept
106 Bucket * ret_val = 0;
107 long offset = (long) &ret_val->key;
108 return (Bucket*) ((long) rec - offset);
111 Bucket * table =
nullptr;
126 bool is_valid_bucket(Bucket * bucket)
const noexcept
128 if (bucket < &table[0] or bucket >= &table[len])
131 int offset_with_base = (
char*) bucket - (
char*) &table[0];
133 return offset_with_base %
sizeof(*bucket) == 0;
138 const Cmp & get_compare()
const {
return cmp; }
140 Cmp & get_compare() {
return cmp; }
147 float __lower_alpha,
float __upper_alpha,
bool __with_resize)
148 : table(nullptr), N(0), len(
Primes::next_prime(__len)),
149 lower_alpha(__lower_alpha), upper_alpha(__upper_alpha), cmp(__cmp),
150 hash_fct(__hash_fct), with_resize(__with_resize)
152 table =
new Bucket [len];
155 OLhashTable(
size_t len, Hash_Fct hash_fct, Hash_Fct, Cmp cmp,
156 float lower_alpha,
float upper_alpha,
bool with_resize)
157 : OLhashTable(len, hash_fct, cmp, lower_alpha, upper_alpha, with_resize) {}
161 OLhashTable(
size_t len = Primes::DefaultPrime,
162 Hash_Fct_Ptr hash_fct = Aleph::dft_hash_fct<Key>,
164 float lower_alpha = hash_default_lower_alpha,
165 float upper_alpha = hash_default_upper_alpha,
166 bool with_resize =
true)
167 : OLhashTable(len, Hash_Fct(hash_fct), cmp,
168 lower_alpha, upper_alpha, with_resize) {}
170 OLhashTable(
size_t len, Hash_Fct_Ptr hash_fct, Hash_Fct_Ptr,
171 Cmp cmp,
float lower_alpha,
float upper_alpha,
bool with_resize)
172 : OLhashTable(len, Hash_fct(hash_fct), cmp,
173 lower_alpha, upper_alpha, with_resize) {}
179 float lower_alpha,
float upper_alpha,
bool with_resize)
180 : OLhashTable(len, hash_fct, cmp,
181 lower_alpha, upper_alpha, with_resize) {}
183 Special_Ctors(OLhashTable, Key);
188 if (table !=
nullptr)
192 void swap(OLhashTable & other) noexcept
194 std::swap(table, other.table);
195 std::swap(N, other.N);
196 std::swap(len, other.len);
197 std::swap(cmp, other.cmp);
198 std::swap(hash_fct, other.hash_fct);
199 std::swap(lower_alpha, other.lower_alpha);
200 std::swap(upper_alpha, other.upper_alpha);
201 std::swap(with_resize, other.with_resize);
204 OLhashTable(
const OLhashTable & other)
205 : OLhashTable(other.len, other.hash_fct, other.cmp,
206 other.lower_alpha, other.upper_alpha, other.with_resize)
208 this->copy_from_table(other);
211 OLhashTable(OLhashTable && other) noexcept : OLhashTable(other)
216 OLhashTable & operator = (
const OLhashTable & other)
225 Bucket * new_table =
new Bucket [other.len];
230 hash_fct = other.hash_fct;
232 lower_alpha = other.lower_alpha;
233 upper_alpha = other.upper_alpha;
236 this->copy_from_table(other);
241 OLhashTable & operator = (OLhashTable && other) noexcept
249 Key *
search(
const Key & key)
const noexcept
251 long i = hash_fct(key) % len, c = 0;
252 while (c < len and table[i].status != EMPTY)
254 if (table[i].status == BUSY and cmp(table[i].key, key))
255 return &table[i].key;
267 Bucket * allocate_bucket(
const Key & key) noexcept
271 size_t i = hash_fct(key) % len;
273 while (table[i].status == BUSY)
275 if (cmp(key, table[i].key))
282 Bucket * bucket = &table[i];
285 bucket->status = BUSY;
291 tuple<Bucket*, bool> hard_allocate_bucket(
const Key & key) noexcept
295 size_t i = hash_fct(key) % len;
296 while (table[i].status == BUSY)
298 if (cmp(key, table[i].key))
299 return make_tuple(&table[i],
true);
305 Bucket * bucket = &table[i];
308 bucket->status = BUSY;
311 return make_tuple(bucket,
false);
321 if (not is_valid_bucket(bucket))
322 throw std::invalid_argument(
"record address is not inside table's range");
324 if (bucket->status != BUSY)
325 throw std::domain_error(
"Bucket containing record is not busy");
328 int i = bucket - &table[0];
329 table[i].status = DELETED;
339 void remove(
const Key & key)
341 Key * key_ptr = search(key);
342 if (key_ptr ==
nullptr)
343 throw std::domain_error(
"Key not in hash table");
345 this->remove_ptr(key_ptr);
348 OHASH_COMMON(OLhashTable);
350 using Stats =
typename OhashCommon<OLhashTable<Key, Cmp>, Key>::Stats;
355 size_t num_busy = 0, num_deleted = 0, num_empty = 0;
356 size_t max_len = std::numeric_limits<size_t>::min();
357 for (
int i = 0; i < len; ++i)
358 switch (table[i].status)
363 const Key & key = table[i].key;
364 long i = hash_fct(key) % len;
369 if (table[i].status == BUSY and cmp(table[i].key, key))
376 max_len = std::max(max_len, count);
377 update_stat_len(lens, count);
382 update_stat_len(lens, 0);
389 float avg = 0, sum = 0;
390 for (
int i = 0; i < lens.
size(); ++i)
398 for (
int i = 0; i < lens.
size(); ++i)
406 stats.num_busy = num_busy;
407 stats.num_deleted = num_deleted;
408 stats.num_empty = num_empty;
409 std::swap(lens, stats.lens);
412 stats.max_len = max_len;
420 template <
typename Key,
class Cmp = Aleph::equal_to<Key>>
425 # endif // TPL_OLHASH_H
OLhashTable(size_t len, Hash_Fct hash_fct, Hash_Fct_Ptr, Cmp cmp, float lower_alpha, float upper_alpha, bool with_resize)
Definition: tpl_olhash.H:178
Key * search(const Key &key) const noexcept
Definition: tpl_olhash.H:249
size_t size() const noexcept
Definition: tpl_dynArray.H:641
~OLhashTable()
Libera toda la memoria ocupada.
Definition: tpl_olhash.H:186
OLhashTable(size_t __len, Hash_Fct __hash_fct, Cmp __cmp, float __lower_alpha, float __upper_alpha, bool __with_resize)
Definition: tpl_olhash.H:146
Definition: htlist.H:1323
void deallocate_bucket(Bucket *bucket)
Definition: tpl_olhash.H:319
Definition: tpl_olhash.H:73