I am working on a project where we are to write a hash table using a given header file. So far everything is working (my get is bugged but I can at least fix that) but I have run into a problem. I have no idea how to rehash an open addressing hash table. I'll provide my structs, my create function, and my put function.
/// The "buckets" in the table
typedef struct Entry_t {
void* key; ///< key must be "hashable"
void* value; ///< value can be any type
} Entry;
/// The hash table
typedef struct Table_t {
Entry** table; ///< table of Entry pointers
size_t size; ///< number of entries in table
size_t capacity; ///< total capacity of table
long (*hash)(void* key); ///< hash function for key
bool (*equals)(void *key1, void* key2); ///< equals function for key comparison
void (*print)(void *key, void* value); ///< print function for table dump debug
size_t collisions; ///< number of collisions throughout life of hash table
size_t rehashes; ///< number of rehashes throughout life of hash table
} Table;
Table* create(long (*hash)(void* key), bool (*equals)(void* key1, void* key2),
void (*print)(void* key1, void* key2))
{
Table* t = (Table*)malloc(sizeof(Table));
if (t == NULL)
{
return NULL;
}
t->size = 0;
t->capacity = INITIAL_CAPACITY;
t->collisions = 0;
t->rehashes = 0;
t->table = (Entry**)calloc(t->capacity, sizeof(Entry*));
t->hash = hash;
t->equals = equals;
t->print = print;
return t;
}
The way I have my code written, t->table[index] is null, so I have to malloc space for it right before I insert the values. Here is my put function.
void* put(Table* t, void* key, void* value) // Rehashing needs to be completed
{
int index = t->hash(key) % t->capacity;
void* old_value = NULL;
int check = 0;
if (t->table[index] != NULL)
{
while (check == 0)
{
if (t->table[index] != NULL)
{
if (t->equals(t->table[index]->key, key) == 0)
{
index = (index + 1) % t->capacity;
}
else // Meaning the keys match, then leave
{
check = 1;
}
}
else // Empty node, meaning the key is NOT in the table
{
check = 1;
}
}
}
if (t->table[index] != NULL) // Meaning the key is in the table, so update the value
{
old_value = t->table[index]->value;
t->table[index]->value = value;
}
else
{
t->size++;
if ((float)t->size / t->capacity > LOAD_THRESHOLD) // Time to rehash
{
// Not sure what to do here
// I was told that I must use realloc, but I am unsure how
}
t->table[index] = malloc(sizeof(Entry));
t->table[index]->key = key;
t->table[index]->value = value;
t->print(key, value);
}
return old_value;
}
At first, inside the if test to see if I should rehash, I wanted to realloc the memory with
t->table = (Entry**)realloc((t->capacity * RESIZE_FACTOR), sizeof(Entry));
However this gave me the error
error: passing argument 1 of 'realloc' makes pointer from integer without a cast [-Werror]
Which I am unsure how to fix/approach.
There is also the matter of reassigning key/value pairs to new index's, as I believe once the capacity changes, the current index's in the table are not representative anymore. Just like realloc, I am unsure how to do this.
Any help is greatly appreciated, thank you!