构造哈希表/哈希函数

时间:2010-06-02 22:58:03

标签: c string hash hashtable hash-function

我想构建一个哈希表,查找字节序列(字符串)中的键,范围从1到15个字节。

我想存储一个整数值,所以我想一个哈希数组就足够了。我很难概念化如何构造一个哈希函数,以便给定密钥可以为数组提供索引。

任何协助都会有很多相关内容。

哈希中的最大条目数为:4081 * 15 + 4081 * 14 + ... 4081 = 4081((15 *(16))/ 2)= 489720。

例如:

int table[489720];

int lookup(unsigned char *key)
{
    int index = hash(key);
    return table[index];
}

哈希函数有哪些好的选择,或者我将如何构建哈希函数?

感谢。

4 个答案:

答案 0 :(得分:3)

要散列C字符串,我总是使用这个函数(取结果%你的散列表的大小):

int hashstring(const char* s) {
  int key = 0;
  while (*s) {
    key = key*37 + *s++;
  }
  return key;
}

我不记得我最初从哪里得到它,但多年来它并没有让我失望。

答案 1 :(得分:2)

你的密钥空间很大(大约2 ^(8 * 15)),所以如果你想要一个完美的哈希,你需要知道489720实际密钥将提前显示。即便如此,即使您允许使用更大的表(例如,非常低的负载系数),实际上也不可能为这些键找到完美的哈希值。我知道找到完美哈希的唯一方法是通过反复试验,随机哈希可能会失败,除非你的表有接近489720 ^ 2个条目。

我强烈建议您使用regular (non-perfect) hashdeal with collisions appropriately,例如与链接:

struct entry {
  unsigned char *key;
  int value;
  struct entry *next;
} *table[1<<20];
int lookup(unsigned char *key) {
  int index = hash(key) % (1<<20);
  for (struct entry *e = table[index]; e != NULL; e = e->next) {
    if (!strcmp(key, e->key)) return e->value;
  }
  // not found
}

我还建议您不要自己实现 - 使用标准库,如c++ hashmap

答案 2 :(得分:0)

如果你想要一个完美的哈希,那么你可以先阅读perfect hashing上的维基百科文章。如果遇到障碍,可以在这里寻求帮助。

答案 3 :(得分:0)

如果表中驻留的字符串的平均数量很少 - 就像10,000个条目一样 - 关联数组将是一种合理的方法,即使使用线性搜索,如果它在现代CPU架构上也是如此。

否则,构造“完美散列”需要检查字符串的每个字符并根据可能的范围计算唯一值。例如,如果密钥中只允许使用26个字符A..Z,则可以使用:

int
hash (const char *key)
{
   int h = 0;
   while (key && *key)
       h = h * 26 + (*key++ - 'A');
   return h;
}