我正在创建一个哈希表,我需要创建一个不仅依赖于字符串键大小的哈希函数,因为周期表元素只有1到3个字符。我怎样才能创建一个哈希函数,给我一个可能基于字符串每个字符的字节的索引?
答案 0 :(得分:5)
几乎字符串上的每个哈希函数都会对字符进行哈希处理;很难看到字符串完全按照它们的长度进行散列。
一个简单的散列函数系列是shift-add-XOR,顾名思义,它使用位移,加法和异或的组合来从字符串中获取散列函数。它易于实现,并且可以很好地分配密钥。
也就是说,如果您保证只使用周期表符号,则可能需要尝试为元素找到完美的哈希函数。这是为您正在使用的数据集定制的哈希函数,从不会发生任何冲突。像gperf
这样的工具可以用来创建这样的函数。
希望这有帮助!
答案 1 :(得分:1)
最简单的解决方案是使用现有的解决方案,如FNV。 但要小心 - 一些非常普遍的哈希函数 当给出很多非常短的字符串时,表现不佳(一个 例如,java.lang.String使用)。对于通用哈希 功能,我通常使用类似的东西:
size_t
hash( std::string const& value )
{
size_t result = 2166136261;
for ( std::string::const_iterator current = value.begin();
current != value.end();
++ current ) {
result = 127 * result + static_cast< unsigned char >( *current );
}
return result;
}
在慢速乘法的机器上,这稍微快一些 比FNV,我还没有找到一个分布的案例 显着更差。
但是,您提到最大字符串长度为3。 在这种情况下,您可以使用更简单的技术:
size_t
hash( std::string const& value )
{
union {
size_t results;
char input[ sizeof( size_t ) ];
} working = 0;
assert( value.size() <= sizeof( size_t ) );
value.copy( working.input, sizeof( size_t ) );
return working.results;
}
这两个都保证了所有字符串的唯一哈希值
长度小于sizeof(
size_t )
的可打印ASCII字符。