编写健壮的整数散列函数

时间:2013-06-21 16:04:33

标签: c hash hashtable

我想为哈希表写一个好的整数哈希函数。即使我怀疑我的哈希表不会太大(比如大小为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等)。问题是我注意到这个哈希函数非常频繁地生成相同的哈希值。有没有办法可以调整它,以便以新的哈希值结束的可能性更大。

1 个答案:

答案 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;
 }

请注意,您需要区分散列函数和将散列映射到插槽或存储桶的代码。我将它们合并在一个函数中,因为它们非常简单,并给它一个正确的名称。另请注意,添加任何熵都是没有意义的,结果不能比原始分布更好。只有当你有更多的输入值并且它们可以相关时才有意义。