I'm having trouble figuring out the destructor for my hashTable class, the destructor is like this:
template <typename ElementType>
HashSet<ElementType>::~HashSet() noexcept
{
for (unsigned int i=0;i<hashCapacity;i++)
{
Node* current = hashTable[i];
while(current != nullptr)
{
Node* entry = current;
current = current->next;
delete[] entry;
}
}
delete[] hashTable;
}
No matter I use either delete[] or delete, it gives me either double-free errors or segmentation fault.
The class template is below:
template <typename ElementType>
class HashSet : public Set<ElementType>
{
public:
// The default capacity of the HashSet before anything has been
// added to it.
static constexpr unsigned int DEFAULT_CAPACITY = 10;
// A HashFunction is a function that takes a reference to a const
// ElementType and returns an unsigned int.
using HashFunction = std::function<unsigned int(const ElementType&)>;
public:
// Initializes a HashSet to be empty so that it will use the given
// hash function whenever it needs to hash an element.
explicit HashSet(HashFunction hashFunction);
// Cleans up the HashSet so that it leaks no memory.
~HashSet() noexcept override;
// add() adds an element to the set. If the element is already in the set,
// this function has no effect. This function triggers a resizing of the
// array when the ratio of size to capacity would exceed 0.8, in which case
// the new capacity should be determined by this formula:
//
// capacity * 2 + 1
//
// In the case where the array is resized, this function runs in linear
// time (with respect to the number of elements, assuming a good hash
// function); otherwise, it runs in constant time (again, assuming a good
// hash function). The amortized running time is also constant.
void add(const ElementType& element) override;
Where my add function and default constructor implementation is like this:
template <typename ElementType>
HashSet<ElementType>::HashSet(HashFunction hashFunction)
: hashFunction{hashFunction}
{
hashCapacity = DEFAULT_CAPACITY;
hashSize = 0;
hashTable = new Node* [hashCapacity];
for (int i=0;i<hashCapacity;++i)
{
hashTable[i] = nullptr;
}
}
template <typename ElementType>
void HashSet<ElementType>::add(const ElementType& element)
{
if (contains(element)==false)
{
if ((hashSize/hashCapacity) > 0.8)
{
}
else
{
unsigned int index = hashFunction(element) % hashCapacity;
hashSize += 1;
Node* add = new Node;
add->next = nullptr;
add->value = element;
if (hashTable[index]==nullptr)
{
hashTable[index] = add;
}
else
{
Node* addNode = hashTable[index];
while(addNode->next != nullptr)
{
addNode = addNode->next;
}
addNode->next = add;
}
}
}
}
Note: that resize hashtable part is incomplete because I'm examining the functionality for my hash table to hold a small amount of value first.