Мне нужно написать собственную хэш-функцию. Если бы я хотел просто сделать простую хеш-функцию, которая отображает каждую букву в строке на числовое значение (т.е. a = 1, b = 2, c = 3,...), есть способ, которым я могу выполнить этот хеш строка без необходимости сначала преобразовывать ее в c-строку, чтобы посмотреть на каждый отдельный char? Есть ли более эффективный способ хеширования строк?
Как я могу передать строку в int с помощью С++?
Ответ 1
Повторите первый вопрос, конечно, например:
int hash = 0;
int offset = 'a' - 1;
for(string::const_iterator it=s.begin(); it!=s.end(); ++it) {
hash = hash << 1 | (*it - offset);
}
относительно второго, существует много лучших способов хэш-строк. Например, см. здесь для нескольких примеров C (легко переводимых на С++ по линиям вышеприведенного фрагмента).
Ответ 2
Из личного опыта я знаю, что это работает и создает хорошие распределения. (Плагиат из http://www.cse.yorku.ca/~oz/hash.html):
djb2
этот алгоритм (k = 33) впервые был дан Дан Бернштейном много лет назад в comp.lang.c. другая версия этого алгоритма (в настоящее время пользуется бернштейном) использует xor: hash (i) = hash (i - 1) * 33 ^ str [i]; магия числа 33 (почему она работает лучше, чем многие другие константы, простые или нет) никогда не была адекватно объяснена.
unsigned long hash(unsigned char *str) {
unsigned long hash = 5381;
int c;
while (c = *str++) {
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
}
return hash;
}
Ответ 3
Вы можете просмотреть каждый char из std::string с помощью оператора []
. Тем не менее, вы можете посмотреть Boost:: Functional/Hash для руководства по лучшей схеме хэширования. Существует также список хэш-функций в c, расположенный здесь.
Ответ 4
Здесь C (++) хэш-функция, которую я нашел в книге Страуструпа:
int hash(const char *str)
{
int h = 0;
while (*str)
h = h << 1 ^ *str++;
return h;
}
Если вы используете его для хэш-таблицы (что делает Stroustrup), вы можете вместо этого вернуть абс хэш по модулю простого числа. Поэтому вместо
return (h > 0 ? h : -h) % N_BUCKETS;
для последней строки.
Ответ 5
xor символы вместе, по четыре за раз.
Ответ 6
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
// a variation on dan bernstein algorithm
// [http://www.cse.yorku.ca/~oz/hash.html]
template<typename Int>
struct hash {
hash() : acc(5381) { }
template<typename Ch>
void operator()(Ch ch) { acc = ((acc << 5) + acc) ^ ch; }
operator Int() const { return acc; }
Int acc;
};
int main(int argc, char* argv[])
{
string s("Hellp, world");
cout << hex << showbase
<< for_each(s.begin(), s.end(), hash<unsigned long long>()) << '\n';
return 0;
}
Ответ 7
Другой способ для небольших строк:
int hash(const char* str) {
int hash = 0;
int c = 0;
while (c < std::strlen(str)) {
hash += (int)str[c] << (int)str[c+1];
c++;
}
return hash;
}
Ответ 8
Вы можете использовать функции-члены operator [] или at класса строк или итераторов для доступа к отдельному char строкового объекта без преобразования его в массив c-style char.
Чтобы хэшировать строковый объект целому числу, вам нужно будет получить доступ к каждому отдельному char строкового объекта, который вы можете сделать как:
for (i=0; i < str.length(); i++) {
// use str[i] or str.at(i) to access ith element.
}