-1

我想为哈希表编写一个好的整数哈希函数。即使我怀疑我的哈希表不会太大(比如大小为 36 个元素),生成哈希值的“键”可能会在 0,20,31,.... 11456,13444 等范围内的值之间发生巨大变化.类似的问题之前已经在这里发布过,我的哈希函数的灵感来自于此处提供的建议答案。

以下是我的表的结构:

  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 等)。问题是我注意到这个散列函数非常频繁地生成相同的散列值。有没有办法可以调整它,以便以新的哈希值结束的机会更多。

4

1 回答 1

1
 unsigned int hash(hash_table_t *hashtable, int key)

这是创建完美哈希函数的一个相当难得的机会。为每个不同的输入值生成唯一值的函数。你不可能做得更好。在这种情况下是可能的,因为输入位数等于输出位数。典型的散列函数需要处理更多的输入位和有限数量的输出位。这造成了不可避免的哈希冲突问题。完美的哈希没有这样的问题。

在这种情况下,完美的哈希函数一如既往地是微不足道的:

 unsigned int getslot(hash_table_t *hashtable, int key)
 {
   return (unsigned)key % hashtable->size;
 }

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

于 2013-06-21T18:16:22.510 回答