Как я могу хэшировать строку в int с помощью c++?
Я должен написать свою собственную хэш-функцию. Если бы я хотел просто сделать простую хэш-функцию, которая сопоставляет каждую букву в строке с числовым значением (т. е. a=1, b=2, c=3, ...), есть ли способ выполнить этот хэш на строке без необходимости сначала преобразовать его в C-строку, чтобы посмотреть на каждый отдельный символ? Есть ли более эффективный способ хэширования строк?
9 ответов
Re первый вопрос, конечно, e.g, что-то вроде:
int hash = 0;
int offset = 'a' - 1;
for(string::const_iterator it=s.begin(); it!=s.end(); ++it) {
hash = hash << 1 | (*it - offset);
}
что касается второго, есть много лучших способов хэширования строк. Е. Г., вижу здесь для нескольких примеров C (легко переводимых на C++ вдоль строк фрагмента выше).
из личного опыта я знаю, что это работает и дает хорошие дистрибутивы. (Заимствованы из http://www.cse.yorku.ca/~oz/hash.html):
djb2
этот алгоритм (k=33) впервые был сообщен Дэном Бернштейном много лет назад в comp.ленг.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;
}
вы можете изучить каждый отдельный символ из строки std::, используя []
оператора. Тем не менее, вы можете посмотреть на Boost:: Functional/Hash для руководства по лучшей схеме хэширования. Существует также список функций хэширования в C located здесь.
вот хэш-функция C ( ++ ), которую я нашел в книге Страуструпа:
int hash(const char *str)
{
int h = 0;
while (*str)
h = h << 1 ^ *str++;
return h;
}
Если вы используете его для хэш-таблицы (что делает Stroustrup), то вы можете вместо этого вернуть abs хэш-модуля простое число. Так что вместо этого
return (h > 0 ? h : -h) % N_BUCKETS;
на последней строке.
C++11 поставляется со стандартной функцией хэширования для строк.
https://en.cppreference.com/w/cpp/string/basic_string/hash
#include <string>
#include<functional> // hash
int main(){
std::string s = "Hello";
std::size_t hash = std::hash<std::string>{}(s);
}
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
// a variation on dan bernstein's 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;
}
другой способ для небольших строк:
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;
}
вы можете использовать функции-члены оператор[] или at класса string или итераторов для доступа к отдельному символу строкового объекта без преобразования его в массив символов c-стиля.
чтобы хэшировать строковый объект в целое число, вам нужно будет получить доступ к каждому отдельному символу строкового объекта, который вы можете сделать как:
for (i=0; i < str.length(); i++) {
// use str[i] or str.at(i) to access ith element.
}