The algorithm in ht_get
is incorrect:
while (ht->table[index] != NULL
&& hash(ht,ckey = get_key(ht->table[index])) == hkey) {
if (ckey == key) return ht->table[index];
index = MODINC(ht->bits,index);
}
You are assuming here that if you find a key with a different hash in your probe sequence, then this means that the key you are looking for is not there. But that's not right. Try the following test program:
#include <stdint.h>
#include <stdio.h>
#include "ht.h"
#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
int main(int argc, char *argv[]) {
uint64_t k[] = {0x12345671, 0x11223344, 0x22334411, 0x33441122};
ht_t *ht = ht_new(2);
for (size_t i = 0; i < ARRAY_LENGTH(k); ++i) {
ht_put(ht, k[i], &k[i]);
}
printf("%p\n", ht_get(ht, k[0]));
return 0;
}
You'll need to run it a few times (because of the randomization in your hash function), but I find that about half the time this prints 0x0
because k[0]
failed to be found in the hash table (even though it must be there since it was the first key that was added).
- The algorithm in
ht_del
is also incorrect. As Knuth writes, "Many computer programmers have great faith in algorithms, and they are surprised to find that the obvious way to delete records from a hash table doesn't work." (The Art of Computer Programming Vol. III, p. 533.)
Also, if the table is full, and if all the keys have the same hash, then ht_get
and ht_del
will also loop infinitelygo into infinite loops.