Browse Source

Added Bucket::erase(), optimized assignment operators

release/0.19
Jessica James 8 years ago
parent
commit
062cbe18a4
  1. 9
      Jupiter/Hash_Table.h
  2. 75
      Jupiter/Hash_Table_Imp.h

9
Jupiter/Hash_Table.h

@ -87,6 +87,13 @@ namespace Jupiter
*/ */
ValueT *remove(const InKeyT &in_key); ValueT *remove(const InKeyT &in_key);
/**
* @brief Erases all entries from the bucket
*
* @return Number of entries erased
*/
size_t erase();
/** /**
* @brief Copy assignment operator * @brief Copy assignment operator
* *
@ -227,7 +234,7 @@ namespace Jupiter
* @param in_buckets Array of buckets to copy entries into * @param in_buckets Array of buckets to copy entries into
* @param in_buckets_size Number of buckets in in_buckets * @param in_buckets_size Number of buckets in in_buckets
*/ */
void copy_to_buckets(Bucket *in_buckets, size_t in_buckets_size); void copy_to_buckets(Bucket *in_buckets, size_t in_buckets_size) const;
Bucket *m_buckets; /** Array of Buckets */ Bucket *m_buckets; /** Array of Buckets */
size_t m_buckets_size; /** Number of buckets */ size_t m_buckets_size; /** Number of buckets */

75
Jupiter/Hash_Table_Imp.h

@ -114,6 +114,15 @@ ValueT *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::remo
return nullptr; return nullptr;
} }
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
size_t Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::erase()
{
size_t length = m_pairs.size();
m_pairs.eraseAndDelete();
return length;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::operator=(const Bucket &in_bucket) typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::operator=(const Bucket &in_bucket)
{ {
@ -209,15 +218,49 @@ void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::shrink()
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::operator=(const Hash_Table &in_table) typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::operator=(const Hash_Table &in_table)
{ {
// TODO: Optimize; can overwrite data instead of deleting and allocationg again if m_buckets_size > in.m_buckets_size if (m_buckets_size >= in_table.m_buckets_size && m_buckets_size <= in_table.m_buckets_size * 2)
{
// We're larger than what we're copying, but not drastically (2x) larger. Just erase our current data and copy their entries.
if (m_length == 0) // we don't need to erase any data
in_table.copy_to_buckets(m_buckets, m_buckets_size);
else
{
// we need to erase data; slightly modified version of copy_to_buckets()
Jupiter::SLList<Bucket::Entry>::Node *node;
size_t index = 0;
while (index != in_table.m_buckets_size)
{
in_table.m_buckets[index].m_pairs.eraseAndDelete();
for (node = in_table.m_buckets[index].m_pairs.getHead(); node != nullptr; node = node->next)
m_buckets[HashF(node->data->key) % m_buckets_size].set(node->data->key, node->data->value);
++index;
}
while (index != m_buckets_size)
{
in_table.m_buckets[index].m_pairs.eraseAndDelete();
++index;
}
}
}
else
{
// m_buckets is either too small to copy the data, or it'd be too wasteful
delete[] m_buckets; delete[] m_buckets;
m_length = in_table.m_length;
m_buckets_size = in_table.m_buckets_size; m_buckets_size = in_table.m_buckets_size;
m_buckets = new Bucket[m_buckets_size]; m_buckets = new Bucket[m_buckets_size];
for (size_t index = 0; index != m_buckets_size; ++index) for (size_t index = 0; index != m_buckets_size; ++index)
m_buckets[index] = in_table.m_buckets[index]; m_buckets[index] = in_table.m_buckets[index];
}
m_length = in_table.m_length;
return *this; return *this;
} }
@ -225,7 +268,20 @@ typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Ha
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::operator=(Hash_Table &&in_table) typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::operator=(Hash_Table &&in_table)
{ {
// TODO: Optimize; can swap empty array instead of always deleting if (m_length == 0)
{
Bucket *old_buckets = m_buckets;
size_t old_buckets_size = m_buckets_size;
m_buckets = in_table.m_buckets;
m_buckets_size = in_table.m_buckets_size;
m_length = in_table.m_length;
in_table.m_buckets = old_buckets;
in_table.m_buckets_size = old_buckets_size;
}
else
{
delete[] m_buckets; delete[] m_buckets;
m_buckets = in_table.m_buckets; m_buckets = in_table.m_buckets;
@ -234,7 +290,10 @@ typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Ha
in_table.m_buckets = new Bucket[1]; in_table.m_buckets = new Bucket[1];
in_table.m_buckets_size = 1; in_table.m_buckets_size = 1;
}
in_table.m_length = 0; in_table.m_length = 0;
return *this; return *this;
} }
@ -299,19 +358,13 @@ void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::expand()
} }
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::copy_to_buckets(Bucket *in_buckets, size_t in_buckets_size) void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::copy_to_buckets(Bucket *in_buckets, size_t in_buckets_size) const
{ {
Jupiter::SLList<Bucket::Entry>::Node *node; Jupiter::SLList<Bucket::Entry>::Node *node;
for (size_t index = 0; index != m_buckets_size; ++index) for (size_t index = 0; index != m_buckets_size; ++index)
{
for (node = m_buckets[index].m_pairs.getHead(); node != nullptr; node = node->next) for (node = m_buckets[index].m_pairs.getHead(); node != nullptr; node = node->next)
in_buckets[HashF(node->data->key) % in_buckets_size].set(node->data->key, node->data->value); in_buckets[HashF(node->data->key) % in_buckets_size].set(node->data->key, node->data->value);
} }
}
/*
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>
*/
#endif // _HASH_TABLE_IMP_H_HEADER #endif // _HASH_TABLE_IMP_H_HEADER
Loading…
Cancel
Save