Track hash Set length

Can be used later to rehash the hash table if it is full up to some
percentage.
This commit is contained in:
Eugen Wissner 2018-04-30 12:42:25 +02:00
parent 18d54b4b18
commit c4424e7e01
2 changed files with 70 additions and 37 deletions

View File

@ -120,6 +120,7 @@ package struct HashArray(alias hasher, K, V = void)
Array!Bucket array; Array!Bucket array;
size_t lengthIndex; size_t lengthIndex;
size_t length;
/* /*
* Returns bucket position for `hash`. `0` may mean the 0th position or an * Returns bucket position for `hash`. `0` may mean the 0th position or an
@ -144,10 +145,15 @@ package struct HashArray(alias hasher, K, V = void)
foreach (ref e; this.array[bucketPosition .. $]) foreach (ref e; this.array[bucketPosition .. $])
{ {
if (e == key || e.status != BucketStatus.used) if (e == key)
{ {
return e; return e;
} }
else if (e.status != BucketStatus.used)
{
++this.length;
return e;
}
} }
if (primes.length == (this.lengthIndex + 1)) if (primes.length == (this.lengthIndex + 1))
@ -207,4 +213,46 @@ package struct HashArray(alias hasher, K, V = void)
{ {
return this.array.length; return this.array.length;
} }
void clear()
{
this.array.clear();
this.length = 0;
}
size_t remove(ref K value)
{
auto bucketPosition = locateBucket(value);
foreach (ref e; this.array[bucketPosition .. $])
{
if (e == value) // Found.
{
e.remove();
--this.length;
return 1;
}
else if (e.status == BucketStatus.empty)
{
break;
}
}
return 0;
}
bool find(ref const K value) const
{
auto bucketPosition = locateBucket(value);
foreach (ref e; this.array[bucketPosition .. $])
{
if (e == value) // Found.
{
return true;
}
else if (e.status == BucketStatus.empty)
{
break;
}
}
return false;
}
} }

View File

@ -314,15 +314,7 @@ if (is(typeof(hasher(T.init)) == size_t))
*/ */
@property size_t length() const @property size_t length() const
{ {
size_t count; return this.data.length;
foreach (ref e; this.data.array[])
{
if (e.status == BucketStatus.used)
{
++count;
}
}
return count;
} }
/// ///
@ -335,6 +327,24 @@ if (is(typeof(hasher(T.init)) == size_t))
assert(set.length == 1); assert(set.length == 1);
} }
/**
* Tells whether the container contains any elements.
*
* Returns: Whether the container is empty.
*/
@property bool empty() const
{
return length == 0;
}
/**
* Removes all elements.
*/
void clear()
{
this.data.clear();
}
/// The maximum number of buckets the container can have. /// The maximum number of buckets the container can have.
enum size_t maxBucketCount = primes[$ - 1]; enum size_t maxBucketCount = primes[$ - 1];
@ -386,20 +396,7 @@ if (is(typeof(hasher(T.init)) == size_t))
*/ */
size_t remove(T value) size_t remove(T value)
{ {
auto bucketPosition = this.data.locateBucket(value); return this.data.remove(value);
foreach (ref e; this.data.array[bucketPosition .. $])
{
if (e == value) // Found.
{
e.remove();
return 1;
}
else if (e.status == BucketStatus.empty)
{
break;
}
}
return 0;
} }
/// ///
@ -427,19 +424,7 @@ if (is(typeof(hasher(T.init)) == size_t))
*/ */
bool opBinaryRight(string op : "in")(auto ref const T value) const bool opBinaryRight(string op : "in")(auto ref const T value) const
{ {
auto bucketPosition = this.data.locateBucket(value); return this.data.find(value);
foreach (ref e; this.data.array[bucketPosition .. $])
{
if (e == value) // Found.
{
return true;
}
else if (e.status == BucketStatus.empty)
{
break;
}
}
return false;
} }
/// ///