Aging_MouthReplace / dlibs /dlib /hash_table /hash_table_kernel_1.h
AshanGimhana's picture
Upload folder using huggingface_hub
9375c9a verified
// Copyright (C) 2003 Davis E. King ([email protected])
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_HASH_TABLE_KERNEl_1_
#define DLIB_HASH_TABLE_KERNEl_1_
#include "hash_table_kernel_abstract.h"
#include "../general_hash/general_hash.h"
#include "../algs.h"
#include "../interfaces/map_pair.h"
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../assert.h"
#include "../serialize.h"
#include <functional>
namespace dlib
{
template <
typename domain,
typename range,
typename mem_manager = default_memory_manager,
typename compare = std::less<domain>
>
class hash_table_kernel_1 : public enumerable<map_pair<domain, range> >,
public pair_remover<domain,range>
{
/*!
INITIAL VALUE
hash_size == 0
table == pointer to an array of num_of_buckets node pointers
num_of_buckets == the number of buckets in the hash table
current_element == 0
at_start_ == true
mask == num_of_buckets-1
CONVENTION
current_element_valid() == (current_element != 0)
element() == current_element->d and current_element->r
at_start_ == at_start()
if (current_element != 0) then
table[current_bucket] == a pointer to the linked list that contains
the node pointed to by current_element
mask == num_of_buckets-1
hash_size = size() == the number of elements in the hash_table and
table == pointer to an array of num_of_buckets node pointers and
num_of_buckets == the number of buckets in the hash table and
for all i:
table[i] == pointer to the first node in a linked list or
table[i] == 0 if this bucket is currently not in use
for all nodes:
d == the domain element stored in this node
r == the range element stored in this node which is associated with
d.
next == pointer to the next node in the linked list or
next == 0 if this is the last node in the linked list
!*/
struct node
{
node* next;
domain d;
range r;
};
class mpair : public map_pair<domain,range>
{
public:
const domain* d;
range* r;
const domain& key(
) const { return *d; }
const range& value(
) const { return *r; }
range& value(
) { return *r; }
};
public:
typedef domain domain_type;
typedef range range_type;
typedef compare compare_type;
typedef mem_manager mem_manager_type;
explicit hash_table_kernel_1(
unsigned long expnum
);
virtual ~hash_table_kernel_1(
);
void clear(
);
unsigned long count (
const domain& item
) const;
void add (
domain& d,
range& r
);
void remove (
const domain& d,
domain& d_copy,
range& r
);
void destroy (
const domain& d
);
const range* operator[] (
const domain& d
) const;
range* operator[] (
const domain& d
);
void swap (
hash_table_kernel_1& item
);
// functions from the remover interface
void remove_any (
domain& d,
range& r
);
// functions from the enumerable interface
inline size_t size (
) const;
bool at_start (
) const;
inline void reset (
) const;
bool current_element_valid (
) const;
const map_pair<domain,range>& element (
) const;
map_pair<domain,range>& element (
);
bool move_next (
) const;
private:
// data members
typename mem_manager::template rebind<node>::other pool;
typename mem_manager::template rebind<node*>::other ppool;
unsigned long hash_size;
node** table;
general_hash<domain> hash;
unsigned long num_of_buckets;
unsigned long mask;
mutable mpair p;
mutable unsigned long current_bucket;
mutable node* current_element;
mutable bool at_start_;
compare comp;
// restricted functions
hash_table_kernel_1(hash_table_kernel_1&);
hash_table_kernel_1& operator=(hash_table_kernel_1&);
};
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
inline void swap (
hash_table_kernel_1<domain,range,mem_manager,compare>& a,
hash_table_kernel_1<domain,range,mem_manager,compare>& b
) { a.swap(b); }
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void deserialize (
hash_table_kernel_1<domain,range,mem_manager,compare>& item,
std::istream& in
)
{
try
{
item.clear();
unsigned long size;
deserialize(size,in);
domain d;
range r;
for (unsigned long i = 0; i < size; ++i)
{
deserialize(d,in);
deserialize(r,in);
item.add(d,r);
}
}
catch (serialization_error& e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type hash_table_kernel_1");
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
hash_table_kernel_1<domain,range,mem_manager,compare>::
hash_table_kernel_1(
unsigned long expnum
) :
hash_size(0),
current_element(0),
at_start_(true)
{
num_of_buckets = 1;
while (expnum != 0)
{
--expnum;
num_of_buckets <<= 1;
}
mask = num_of_buckets-1;
table = ppool.allocate_array(num_of_buckets);
for (unsigned long i = 0; i < num_of_buckets; ++i)
{
table[i] = 0;
}
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
hash_table_kernel_1<domain,range,mem_manager,compare>::
~hash_table_kernel_1(
)
{
for (unsigned long i = 0; i < num_of_buckets; ++i)
{
// delete this linked list
node* temp = table[i];
while (temp)
{
node* t = temp;
temp = temp->next;
pool.deallocate(t);
}
table[i] = 0;
}
ppool.deallocate_array(table);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void hash_table_kernel_1<domain,range,mem_manager,compare>::
clear(
)
{
if (hash_size > 0)
{
for (unsigned long i = 0; i < num_of_buckets; ++i)
{
// delete this linked list
node* temp = table[i];
while (temp)
{
node* t = temp;
temp = temp->next;
pool.deallocate(t);
}
table[i] = 0;
}
hash_size = 0;
}
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
size_t hash_table_kernel_1<domain,range,mem_manager,compare>::
size(
) const
{
return hash_size;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
unsigned long hash_table_kernel_1<domain,range,mem_manager,compare>::
count(
const domain& d
) const
{
unsigned long items_found = 0;
node* temp = table[hash(d)&mask];
while (temp != 0)
{
// look for an element equivalent to d
if ( !(comp(temp->d , d) || comp(d , temp->d)) )
{
++items_found;
}
temp = temp->next;
}
return items_found;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void hash_table_kernel_1<domain,range,mem_manager,compare>::
add(
domain& d,
range& r
)
{
unsigned long hash_value = hash(d)&mask;
// make a new node for this item
node& temp = *(pool.allocate());
exchange(d,temp.d);
exchange(r,temp.r);
// add this new node to the head of the linked list in bucket number hash_value
temp.next = table[hash_value];
table[hash_value] = &temp;
++hash_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void hash_table_kernel_1<domain,range,mem_manager,compare>::
destroy(
const domain& d
)
{
node* last;
const unsigned long hash_value = hash(d)&mask;
node* temp = table[hash_value];
// if there is more than one thing in this bucket
if (temp->next != 0)
{
// start looking with the second item in the list
last = temp;
temp = temp->next;
while (true)
{
// if we hit the end of the list without finding item then it must
// be the first element in the list so splice it out
if (temp == 0)
{
temp = table[hash_value];
table[hash_value] = temp->next;
break;
}
// look for an element equivalent to item
if ( !(comp(temp->d , d) || comp(d , temp->d)) )
{
// splice out the node we want to remove
last->next = temp->next;
break;
}
last = temp;
temp = temp->next;
}
}
// else there is only one node in this linked list
else
{
table[hash_value] = 0;
}
pool.deallocate(temp);
--hash_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void hash_table_kernel_1<domain,range,mem_manager,compare>::
remove(
const domain& d,
domain& d_copy,
range& r
)
{
node* last;
const unsigned long hash_value = hash(d)&mask;
node* temp = table[hash_value];
// if there is more than one thing in this bucket
if (temp->next != 0)
{
// start looking with the second item in the list
last = temp;
temp = temp->next;
while (true)
{
// if we hit the end of the list without finding item then it must
// be the first element in the list so splice it out
if (temp == 0)
{
temp = table[hash_value];
table[hash_value] = temp->next;
break;
}
// look for an element equivalent to item
if ( !(comp(temp->d , d) || comp(d , temp->d)) )
{
// splice out the node we want to remove
last->next = temp->next;
break;
}
last = temp;
temp = temp->next;
}
}
// else there is only one node in this linked list
else
{
table[hash_value] = 0;
}
exchange(d_copy,temp->d);
exchange(r,temp->r);
pool.deallocate(temp);
--hash_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void hash_table_kernel_1<domain,range,mem_manager,compare>::
remove_any(
domain& d,
range& r
)
{
unsigned long i = 0;
// while the ith bucket is empty keep looking
while (table[i] == 0)
{
++i;
}
// remove the first node in the linked list in the ith bucket
node& temp = *(table[i]);
exchange(temp.d,d);
exchange(temp.r,r);
table[i] = temp.next;
pool.deallocate(&temp);
--hash_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
const range* hash_table_kernel_1<domain,range,mem_manager,compare>::
operator[](
const domain& d
) const
{
node* temp = table[hash(d)&mask];
while (temp != 0)
{
// look for an element equivalent to item
if ( !(comp(temp->d , d) || comp(d , temp->d)) )
return &(temp->r);
temp = temp->next;
}
return 0;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
range* hash_table_kernel_1<domain,range,mem_manager,compare>::
operator[](
const domain& d
)
{
node* temp = table[hash(d)&mask];
while (temp != 0)
{
// look for an element equivalent to item
if ( !(comp(temp->d , d) || comp(d , temp->d)) )
return &(temp->r);
temp = temp->next;
}
return 0;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void hash_table_kernel_1<domain,range,mem_manager,compare>::
swap(
hash_table_kernel_1<domain,range,mem_manager,compare>& item
)
{
exchange(mask,item.mask);
exchange(table,item.table);
exchange(hash_size,item.hash_size);
exchange(num_of_buckets,item.num_of_buckets);
exchange(current_bucket,item.current_bucket);
exchange(current_element,item.current_element);
exchange(at_start_,item.at_start_);
pool.swap(item.pool);
ppool.swap(item.ppool);
exchange(p,item.p);
exchange(comp,item.comp);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// enumerable function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool hash_table_kernel_1<domain,range,mem_manager,compare>::
at_start (
) const
{
return at_start_;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void hash_table_kernel_1<domain,range,mem_manager,compare>::
reset (
) const
{
at_start_ = true;
current_element = 0;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool hash_table_kernel_1<domain,range,mem_manager,compare>::
current_element_valid (
) const
{
return (current_element != 0);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
const map_pair<domain,range>& hash_table_kernel_1<domain,range,mem_manager,compare>::
element (
) const
{
p.d = &(current_element->d);
p.r = &(current_element->r);
return p;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
map_pair<domain,range>& hash_table_kernel_1<domain,range,mem_manager,compare>::
element (
)
{
p.d = &(current_element->d);
p.r = &(current_element->r);
return p;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool hash_table_kernel_1<domain,range,mem_manager,compare>::
move_next (
) const
{
if (at_start_)
{
at_start_ = false;
// if the queue is empty then there is nothing to do
if (hash_size == 0)
{
return false;
}
else
{
// find the first element in the hash table
for (current_bucket = 0; true ; ++current_bucket)
{
if (table[current_bucket] != 0)
{
current_element = table[current_bucket];
break;
}
}
return true;
}
}
else
{
// if we have already enumerated every element
if (current_element == 0)
{
return false;
}
else
{
// find the next element if it exists
if (current_element->next != 0)
{
current_element = current_element->next;
return true;
}
else
{
// find next bucket with something in it
for (current_bucket+=1; current_bucket<num_of_buckets; ++current_bucket)
{
if (table[current_bucket] != 0)
{
// we just found the next bucket
current_element = table[current_bucket];
break;
}
}
// make sure we actually found another nonempty bucket
if (current_bucket == num_of_buckets)
{
// we didn't find anything
current_element = 0;
return false;
}
else
{
// we found another bucket
return true;
}
}
}
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_HASH_TABLE_KERNEl_1_