构造哈希表/哈希函数
我想构建一个哈希表,查找从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]; }
哈希函数有什么好的选择,或者我将如何构建一个?
谢谢。
为了散列C字符串,我总是使用这个函数(取结果%你的散列表的大小):
int hashstring(const char* s) { int key = 0; while (*s) { key = key*37 + *s++; } return key; }
我不记得我最初从哪里得到它,但多年来它并没有让我失望。
你的密钥空间很大(大约2 ^(8 * 15)),所以如果你想要一个完美的哈希,你需要知道489720实际密钥将提前显示。 即便如此,即使您允许更大的表(也称为非常低的负载因子),实际上不可能为这些键找到完美的哈希值。 我知道找到完美哈希的唯一方法是通过反复试验,并且随机哈希可能会失败,除非你的表有接近489720 ^ 2个条目。
我强烈建议使用常规(非完美)哈希并适当处理冲突 ,例如使用链接:
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这样的标准库。
如果你想要一个完美的哈希,那么你可以从阅读完整哈希的维基百科文章开始。 如果遇到障碍,可以在这里寻求帮助。
如果表中驻留的字符串的平均数量很少 – 就像10,000个条目一样 – 关联数组将是一种合理的方法,即使使用线性搜索,如果它在现代CPU架构上也是如此。
否则,构造“完美散列”需要检查字符串的每个字符并基于可能的范围计算唯一值。 例如,如果密钥中只允许使用26个字符A..Z,则可以使用:
int hash (const char *key) { int h = 0; while (key && *key) h = h * 26 + (*key++ - 'A'); return h; }