You recompute the hash during resize operations. As your hash functions grows more powerful, this gets more expensive. I'd suggest storing the hash value in the key record, and not doing any hashing during resize - just compute the stored hash value modulemodulo the new table size.
Your type names are a mix of Pascal case and the C
_tsuffix. I'd suggest that you pick one: either usehashtable_torHashTableas your type name.Further, why not include the pointer in the type definition? Instead of declaring
HashTable *ht;it would be easier to declareHashTable ht;and let the type be opaque.You are leaking names into the outside. The various table-entry functions should definitely be prefixed with
te_(new,hash, andlookup). Ideally, they should be declaredstaticand completely hidden from outside access.Consider storing your hash/key/value entries in a simple dynamic array. You can then create a separate array of shorts or ints (depending on size) to serve as your hash space. You would hash into the hash space, then use that to find an index into the main table of entries. This lets you store the entries in insertion order (which can be useful), and lets you access the hash space using open addressing with a fairly high degree of locality. (You could even use
unsigned charindexes in your hash space, if you felt there were enough use cases for small tables. Keep in mind that the size of the index is determined by the number of entries, not the size of the hash space: you could have 1024 buckets with < 256 entries and still useucharindexes - damn few collisions, too, I'd bet.)