如果您不熟悉通用散列,它主要是尝试使用一些涉及随机性的相当简单的数学来保证少量的冲突(相反,例如使用普通的旧模数)。问题是它对我不起作用:
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中查看我的 main 。
我的问题是:这个结果可以预期吗?对于使用模数已经表现不佳的输入,通用散列是否表现得更好?还是我只是搞砸了我的实施(更有可能)。
提前非常感谢!