【发布时间】:2017-05-08 23:54:46
【问题描述】:
如果您不熟悉universal hashing,这主要是为了保证较少的冲突(相反,例如使用普通的旧模数),使用一些涉及随机性的相当简单的数学。问题是它对我不起作用:
size_t hash_modulo(const int value) {
return (size_t) (value % TABLE_SIZE);
}
// prime 491 is used because its > 128, which is the size of the hash table
size_t hash_universal(const int value) {
const size_t a = (size_t) (rand() % 491 + 1);
const size_t b = (size_t) (rand() % 491);
//printf("a: %zu, b:%zu\n", a, b);
return ((a * value + b) % 491) % TABLE_SIZE;
}
我先测试模哈希,确定最长的链长(链长是指一个哈希桶的大小):
size_t get_max_chain_length(int input[TABLE_SIZE], size_t (*hash_function)(const int)) {
HashTable *hash_table = hash_table_create(hash_function);
if (!hash_table) {
return 0;
}
for (size_t i = 0; i < TABLE_SIZE; ++i) {
hash_table_add(hash_table, input[i]);
}
size_t maximum_chain_length = 0;
for (int j = 0; j < TABLE_SIZE; ++j) {
const size_t length = length_of_(hash_table->rows[j]);
maximum_chain_length = (length > maximum_chain_length) ? length : maximum_chain_length;
}
//hash_table_print(hash_table);
hash_table_destroy(hash_table);
return maximum_chain_length;
}
我选择了一个导致一个非常大的链的输入(id est 一个使用普通模数表现不佳的输入),并将这个与通用散列相结合。通用散列使用随机性,因此我可以采用恒定输入并仍然得到不同的结果。
问题来了。我尝试了 100 个大小为 128 的随机输入数组,并计算平均最长链和总最长链,但两种算法的性能相似。
您可以在我的repo 中查看我的主要内容。
我的问题是:这个结果是可以预期的吗?对于使用模数已经表现不佳的输入,通用散列是否表现得更好?还是我只是搞砸了我的实施(更有可能)。
提前非常感谢!
【问题讨论】:
-
等等,您要为每个哈希访问重新计算
a和b?这有什么意义? -
在这次尝试中
a和b应该是static吗? -
@melpomene:如果它们是静态的,那么函数总是会将相同的输入散列到同一个桶中?
-
@WhozCraig 见上文
-
因为您的方法无法实际实现可用的哈希表。
标签: c hash hashtable modulo universal-hashing