10 # include <hash-dry.H>
11 # include <hash-fct.H>
12 # include <tpl_dynArray.H>
14 using namespace Aleph;
52 template <
typename Key,
class Cmp = Aleph::equal_to<Key>>
59 typedef Key Item_Type;
64 enum Status { EMPTY, BUSY, DELETED };
66 enum Probe { NO_PROBED, FIRST_PROBE, SECOND_PROBE, LINEAR_PROBE };
72 unsigned probe_type : 4;
73 unsigned int probe_counter;
75 Bucket() : status(EMPTY), probe_type(NO_PROBED), probe_counter(0)
81 probe_type = NO_PROBED;
101 Bucket * allocate_bucket(
Bucket & bucket,
unsigned char probe_type)
103 I(bucket.status != BUSY);
106 bucket.status = BUSY;
107 bucket.probe_type = probe_type;
108 bucket.probe_counter++;
113 void decrease_probe_counter(Bucket * bucket)
115 I(bucket->status == BUSY or bucket->status == DELETED);
117 bucket->probe_counter--;
118 if (bucket->probe_counter == 0)
119 bucket->status = EMPTY;
122 void deallocate_bucket(Bucket * bucket)
124 I(bucket->status == BUSY);
126 bucket->status = DELETED;
127 const Key & key = bucket->key;
129 const size_t i_fst = (*hash_fct)(key) % len;
130 if (&table[i_fst] == bucket)
132 I(Cmp () (table[i_fst].key, key));
133 I(table[i_fst].probe_type == FIRST_PROBE);
138 const size_t i_snd = (*second_hash_fct)(key) % len;
139 if (&table[i_snd] == bucket)
141 I(Cmp () (table[i_snd].key, key));
142 I(table[i_snd].probe_type == SECOND_PROBE);
143 decrease_probe_counter(&table[i_fst]);
148 decrease_probe_counter(&table[i_fst]);
149 decrease_probe_counter(&table[i_snd]);
151 for (index_forward(i); &table[i] != bucket; index_forward(i))
153 I(table[i].status != EMPTY);
154 decrease_probe_counter(&table[i]);
156 I(Cmp () (table[i].key, key));
157 I(table[i].probe_type == LINEAR_PROBE);
161 decrease_probe_counter(bucket);
165 size_t index_forward(
size_t & i)
const
173 size_t index_backward(
size_t & i)
const
181 static Bucket * key_to_bucket(Key * rec)
183 Bucket * ret_val = 0;
184 const long offset = (long) &ret_val->key;
185 return (Bucket*) ((long) rec - offset);
188 bool is_valid_bucket(Bucket * bucket)
190 if (bucket < &table[0] or bucket >= &table[len])
193 const int offset_with_base = (
char*) bucket - (
char*) &table[0];
194 return offset_with_base %
sizeof(*bucket) == 0;
197 size_t bucket_to_index(Bucket * bucket)
199 I(is_valid_bucket(bucket));
200 return bucket - &table[0];
207 std::swap(table, other.table);
208 std::swap(hash_fct, other.hash_fct);
209 std::swap(second_hash_fct, other.second_hash_fct);
210 std::swap(N, other.N);
211 std::swap(len, other.len);
225 Hash_Fct __second_hash_fct = Aleph::snd_hash_fct<Key>,
226 const size_t __len = Primes::DefaultPrime,
227 const float & __lower_alpha = hash_default_lower_alpha,
228 const float & __upper_alpha = hash_default_upper_alpha,
229 const bool __with_resize =
true)
230 : table(NULL), hash_fct(__first_hash_fct),
231 second_hash_fct(__second_hash_fct), len(Primes::next_prime(__len)),
232 lower_alpha(__lower_alpha), upper_alpha(__upper_alpha),
233 N(0), with_resize(__with_resize)
235 table =
new Bucket[len];
246 :
ODhashTable(other.hash_fct, other.second_hash_fct, other.len,
247 other.lower_alpha, other.upper_alpha, other.with_resize)
250 copy_from_table(other);
254 :
ODhashTable(other.hash_fct, other.second_hash_fct, other.len,
255 other.lower_alpha, other.upper_alpha, other.with_resize)
270 Bucket * new_table =
new Bucket [other.len];
275 hash_fct = other.hash_fct;
276 second_hash_fct = other.second_hash_fct;
277 lower_alpha = other.lower_alpha;
278 upper_alpha = other.upper_alpha;
279 with_resize = other.with_resize;
282 copy_from_table(other);
295 Generic_Traverse(Key);
296 Functional_Methods(Key);
303 const size_t i_fst = (*hash_fct)(key) % len;
304 if (table[i_fst].status == EMPTY)
307 if (table[i_fst].status == BUSY and Cmp() (table[i_fst].key, key))
309 I(table[i_fst].probe_type == FIRST_PROBE);
310 I(table[i_fst].probe_counter > 0);
311 return &table[i_fst].key;
314 const size_t i_snd = (*second_hash_fct)(key) % len;
316 if (table[i_snd].status == EMPTY)
319 if (table[i_snd].status == BUSY and Cmp() (table[i_snd].key, key))
321 I(table[i_snd].probe_type == SECOND_PROBE);
322 I(table[i_snd].probe_counter > 0);
323 return &table[i_snd].key;
331 switch (table[i].status)
334 I(table[i].probe_counter == 0);
337 I(table[i].probe_counter > 0);
338 if (Cmp() (table[i].key, key))
340 I(table[i].probe_type == LINEAR_PROBE);
341 return &table[i].key;
345 I(table[i].probe_counter > 0);
347 default: ERROR(
"ODhashTable search: inconsistent bucket status");
354 Hash_Fct get_second_hash_fct()
const {
return second_hash_fct; }
356 void set_second_hash_fct(
Hash_Fct fct)
358 second_hash_fct = fct;
363 Bucket * allocate_bucket(
const Key & key)
366 throw std::overflow_error(
"Hash table is full");
368 const size_t i_fst = (*hash_fct)(key) % len;
369 if (table[i_fst].status != BUSY)
370 return allocate_bucket(table[i_fst], FIRST_PROBE);
372 if (Cmp () (table[i_fst].key, key))
375 const size_t i_snd = (*second_hash_fct)(key) % len;
376 if (table[i_snd].status != BUSY)
378 table[i_fst].probe_counter++;
379 return allocate_bucket(table[i_snd], SECOND_PROBE);
382 if (Cmp () (table[i_snd].key, key))
386 for (
int c = 0; c < len; ++c)
389 switch (table[i].status)
392 if (Cmp() (table[i].key, key))
394 for (
int k = 0; k < c; ++k)
397 table[i].probe_counter--;
404 table[i_fst].probe_counter++;
405 table[i_snd].probe_counter++;
406 return allocate_bucket(table[i], LINEAR_PROBE);
407 default: ERROR(
"ODhashTable: Invalid bucket status");
break;
409 table[i].probe_counter++;
420 void remove_bucket(Bucket * bucket)
422 if (not is_valid_bucket(bucket))
423 throw std::invalid_argument(
"key pty does not belong to hash table");
425 if (bucket->status != BUSY)
426 throw std::domain_error(
"Bucket containing key is not BUSY");
428 deallocate_bucket(bucket);
432 bool process_entry_for_remove(Bucket * bucket,
const Key & key)
434 switch (bucket->status)
437 throw std::domain_error(
"Key not in hash table");
439 if (Cmp () (bucket->key, key))
441 bucket->status = DELETED;
442 decrease_probe_counter(bucket);
446 decrease_probe_counter(bucket);
448 default: ERROR(
"Inconsistent bucket status");
455 void remove(
const Key & key)
460 const size_t i_fst = (*hash_fct)(key) % len;
461 if (process_entry_for_remove(&table[i_fst], key))
464 const size_t i_snd = (*second_hash_fct)(key) % len;
465 if (process_entry_for_remove(&table[i_snd], key))
469 for (
int c = 0; i < len; ++c)
472 if (process_entry_for_remove(&table[i], key))
487 size_t num_busy = 0, num_deleted = 0, num_empty = 0;
488 size_t max_len = std::numeric_limits<size_t>::min();
489 for (
int i = 0; i < len; ++i)
490 switch (table[i].status)
495 const Key & key = table[i].key;
497 const size_t i_fst = (*hash_fct)(key) % len;
498 if (Cmp () (table[i_fst].key, key))
500 I(table[i_fst].probe_type == FIRST_PROBE);
501 I(table[i_fst].probe_counter > 0);
507 size_t i_snd = (*second_hash_fct)(key) % len;
508 if (Cmp () (table[i_snd].key, key))
510 I(table[i_snd].probe_type == SECOND_PROBE);
511 I(table[i_snd].probe_counter > 0);
516 for (
size_t i = index_forward(i_snd);
true; index_forward(i))
518 if (table[i].status == BUSY and
519 Cmp () (table[i].key, key))
525 max_len = std::max(max_len, count);
526 update_stat_len(lens, count);
531 update_stat_len(lens, 0);
538 float avg = 0, sum = 0;
539 for (
int i = 0; i < lens.
size(); ++i)
547 for (
int i = 0; i < lens.
size(); ++i)
555 stats.num_busy = num_busy;
556 stats.num_deleted = num_deleted;
557 stats.num_empty = num_empty;
558 std::swap(lens, stats.lens);
561 stats.max_len = max_len;
590 # endif // TPL_ODHASH_H
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Definition: ahAlgo.H:127
ODhashTable(Hash_Fct __first_hash_fct=Aleph::dft_hash_fct< Key >, Hash_Fct __second_hash_fct=Aleph::snd_hash_fct< Key >, const size_t __len=Primes::DefaultPrime, const float &__lower_alpha=hash_default_lower_alpha, const float &__upper_alpha=hash_default_upper_alpha, const bool __with_resize=true)
Definition: tpl_odhash.H:224
size_t size() const
Retorna dimensión actual (más lejano índice escrito)
Definition: tpl_dynArray.H:523
Key * search(const Key &key) const
Definition: tpl_odhash.H:301
Definition: tpl_odhash.H:68
~ODhashTable()
Libera toda la tabla hash.
Definition: tpl_odhash.H:239
Definition: tpl_dynArray.H:70
Definition: tpl_odhash.H:53
size_t(* Hash_Fct)(const Key &)
El tipo de función hash.
Definition: tpl_odhash.H:62