我想为哈希表写一个好的整数哈希函数。即使我怀疑我的哈希表不会太大(比如大小为36的元素),生成哈希值的“密钥”也会大不相同,范围从0,20,31,...... 11456,13444等。 。 之前已经发布了类似的问题,我的哈希函数受到here提供的答案的启发。
以下是我桌子的结构:
typedef struct _list_t_ {
int key;
int value;
struct _list_t_ *next;
} list_t;
typedef struct _hash_table_t_ {
int size; /* the size of the table */
list_t **table; /* the table elements */
} hash_table_t;
以下是我当前的哈希函数:
unsigned int hash(hash_table_t *hashtable, int key)
{
unsigned int hashval;
hashval = 0;
hashval = key;
hashval = ((hashval >> 16) ^ hashval) * 0x45d9f3b;
hashval = ((hashval >> 16) ^ hashval) * 0x45d9f3b;
hashval = ((hashval >> 16) ^ hashval);
return hashval % hashtable->size; // MOD done to keep within the range of the table size
}
如上所述,产生散列值的“密钥”变化很大(值范围从0,20,31,...... 11456,13444等)。问题是我注意到这个哈希函数非常频繁地生成相同的哈希值。有没有办法可以调整它,以便以新的哈希值结束的可能性更大。
答案 0 :(得分:1)
unsigned int hash(hash_table_t *hashtable, int key)
这是一个创建完美哈希函数的难得机会。为每个不同输入值生成唯一值的函数。你不可能做得更好。在这种情况下可能是因为输入位的数量等于输出位的数量。典型的散列函数需要处理更多的输入位和有限数量的输出位。这就产生了哈希冲突不可避免的问题。完美哈希没有这样的问题。
在这种情况下,完美的哈希函数一如既往地是微不足道的:
unsigned int getslot(hash_table_t *hashtable, int key)
{
return (unsigned)key % hashtable->size;
}
请注意,您需要区分散列函数和将散列映射到插槽或存储桶的代码。我将它们合并在一个函数中,因为它们非常简单,并给它一个正确的名称。另请注意,添加任何熵都是没有意义的,结果不能比原始分布更好。只有当你有更多的输入值并且它们可以相关时才有意义。