我必须编写自己的哈希函数。如果我想制作简单的哈希函数,将字符串中的每个字母映射到一个数值(即a = 1,b = 2,c = 3,...),有没有办法可以执行此哈希一个字符串,而不必先将其转换为一个c字符串来查看每个字符?是否有更有效的散列字符串方法?
答案 0 :(得分:8)
根据个人经验,我知道这种方法有效并且可以产生良好的分布。 (抄袭http://www.cse.yorku.ca/~oz/hash.html):
djb2
这个算法(k = 33)是多年前dan bernstein在comp.lang.c中首次报道的。该算法的另一个版本(现在bernstein青睐)使用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;
}
答案 1 :(得分:7)
重新提出第一个问题,例如:
int hash = 0;
int offset = 'a' - 1;
for(string::const_iterator it=s.begin(); it!=s.end(); ++it) {
hash = hash << 1 | (*it - offset);
}
关于第二种,有很多更好的方法来散列字符串。例如,请参阅here了解一些C示例(可以根据上面的代码片段轻松翻译成C ++)。
答案 2 :(得分:5)
您可以使用[]
运算符检查std :: string中的每个字符。但是,您可以查看Boost::Functional/Hash以获得有关更好的哈希方案的指导。 c中还有一个散列函数列表here。
答案 3 :(得分:5)
这是我在Stroustrup的书中找到的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;
表示最后一行。
答案 4 :(得分:1)
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);
}
答案 5 :(得分:1)
只需发布对Arnestig的djb2算法的改进,使其对constexpr友好。 我必须删除该参数的无符号限定符,以便它可以与文字字符串一起使用。
constexpr unsigned long hash(const char *str) {
unsigned long hash = 5381;
while (int c = *str++) {
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
}
return hash;
}
答案 6 :(得分:0)
将角色放在一起,一次四个。
答案 7 :(得分:0)
#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;
}
答案 8 :(得分: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;
}
答案 9 :(得分:-2)
您可以使用字符串类或迭代器的成员函数operator[]或at来访问字符串对象的单个char,而无需将其转换为c样式的char数组。
要将字符串对象散列为整数,您必须访问字符串对象的每个字符,您可以这样做:
for (i=0; i < str.length(); i++) {
// use str[i] or str.at(i) to access ith element.
}