Я использую эту функцию для cycli c shift:
int hashcyclic(char *p, int len)
{
unsigned int h = 0;
int i;
for (i = 0; i < len; i++)
{
h = (h << 5) | (h >> 27);
h += (unsigned int)p[i];
}
return h%TABLESIZE;
}
В текстовом файле с примерно 20K строками (одно слово / строка) общее количество коллизий составляет 45187. В текстовом файле с 40К + строк (опять же, одно слово / строка) - 12922252 (!) Коллизии с тем же алгоритмом.
При полиномиальном хешировании:
int hashpoly(char *K)
{
int h = 0, a = 33;
for (; *K != '\0'; K++)
h = (a * h + *K) % TABLESIZE;
return h;
}
Теперь я получаю около 25К коллизий на файл 20K слов и 901K коллизий в файле слов 40K (почти в 12 раз меньше, чем cycli c shift).
Мой вопрос: имеет ли это смысл или одна из моих реализаций испортилась? Я ожидал, что cycli c будет самым быстрым для моих строк (файл слов 40K представляет собой серию слов из 8 букв, разделенных символом новой строки), но полиномиальные столкновения значительно реже.
int HashInsertPoly(Table T, KeyType K, InfoType I)
{
int i;
int ProbeDecrement;
i = hashpoly(K);
ProbeDecrement = p(K);
while (T[i].Key[0] != EmptyKey)
{
totalcol++;
T[i].Info.col++;
i -= ProbeDecrement;
if (i < 0)
i += TABLESIZE;
}
strcpy(T[i].Key, K);
insertions++;
/*T[i].Info = I;*/
return i;
}
Та же функция HashInsert применяется к ha sh с cycli c shift, за исключением того, что теперь я вызываю hashcycli c вместо hashpoly