为boost哈希映射定义自定义哈希函数
Defining a custom hash-function for boost hash map
我对C++非常陌生,我需要将一些用C编写的代码转换为C++。问题是,我发现C++语法在运行中很难理解。我希望使用无序的boost散列映射,并希望定义自己的散列函数。我查了一下如何做到这一点,然后发现了这段代码:
struct ihash
: std::unary_function<std::string, std::size_t>
{
std::size_t operator()(std::string const& x) const
{
std::size_t seed = 0;
std::locale locale;
for(std::string::const_iterator it = x.begin();
it != x.end(); ++it)
{
boost::hash_combine(seed, std::toupper(*it, locale));
}
return seed;
}
};
Which you can then use in a case insensitive dictionary:
boost::unordered_map<std::string, int, ihash, iequal_to> idictionary;
我有以下散列函数:
unsigned long hash (unsigned char *str)
{
unsigned long hash = 5381;
int c;
while(c = *str++)
hash = ((hash << 5) + hash) + c; /* hash + 33 + c */
hash %= outer_relation->hash_table.bucket_count();
return hash;
}
有人能帮我转换一下吗。特别是,种子和联合收割机负责什么?
第一个(ihash
)是一个通用散列,以函数对象的形式实现。这有几个优点:
- 它是通用的,也就是说,您可以在不了解/不关心内部组织的情况下,将它与不同容量/负载因子的哈希表一起使用
-
因为它是一个可调用的对象,并且是默认可构造的,所以实际上可以"直接"实例化无序映射:
boost::unordered_map<std::string, int, ihash, iequal_to> idictionary;
其随后将使用默认构造的
ihash
的实例作为散列函数(对于iequal_to
也是如此)。
第二个看起来像是一个硬连接到哈希表实现中的哈希函数。显然,这个哈希表实现假设所有键都必须是unsigned char*
,并且它派生了一个bucket索引作为哈希实现的一部分。注:
-
您无法轻松地将其用于默认的可构建映射:
boost::unordered_map<std::string, int, unsigned long(*)(unsigned char*), iequal_to> idictionary;
因为这将导致散列函数的CCD_ 5实例。因此,您最终会一直将
&hash
传递给构造函数重载。很难对代码进行推理,因为只要原型与匹配,就不可能传递错误的函数指针 -
此函数假定密钥不能包含嵌入的NUL字符(这不是
std::string
的限制 - 此函数的常量不正确(这意味着除非添加常量,例如
size_t (*)(unsigned char const*)
,否则无法使其适用于map
或unordered_map
)
除了这些观察结果之外,这两个函数基本上做相同的工作,其中ihash
根据全局C++区域设置进行大小写折叠(请参阅文档)。
我不太确定你被困在哪里了,因为你的样本看起来应该相对完整?所以,这里有一个独立的小样本,以防它帮助你摆脱困境:
#include <boost/unordered_map.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <iostream>
namespace hash_examples
{
struct iequal_to
: std::binary_function<std::string, std::string, bool>
{
iequal_to() {}
explicit iequal_to(std::locale const& l) : locale_(l) {}
template <typename String1, typename String2>
bool operator()(String1 const& x1, String2 const& x2) const
{
return boost::algorithm::iequals(x1, x2, locale_);
}
private:
std::locale locale_;
};
struct ihash
: std::unary_function<std::string, std::size_t>
{
ihash() {}
explicit ihash(std::locale const& l) : locale_(l) {}
template <typename String>
std::size_t operator()(String const& x) const
{
std::size_t seed = 0;
for(typename String::const_iterator it = x.begin();
it != x.end(); ++it)
{
boost::hash_combine(seed, std::toupper(*it, locale_));
}
return seed;
}
private:
std::locale locale_;
};
}
int main()
{
using namespace hash_examples;
boost::unordered_map<std::string, int, ihash, iequal_to> map;
map.emplace("one", 1);
map.emplace("two", 2);
map.emplace("three", 3);
std::cout << map.at("TWO");
}
请注意,hash_examples
直接来自http://www.boost.org/doc/libs/1_55_0/libs/unordered/examples/case_insensitive.hpp
查看Coliru直播
如果你想使用自己的hash,为什么不实现这样的ihash呢?
struct ihash : std::unary_function<std::string, std::size_t> {
std::size_t operator()(std::string const& value) const {
std::size_t hash = 5381;
const char* str = value.c_str();
int c;
while(c = *str++)
hash = ((hash << 5) + hash) + c; /* hash + 33 + c */
hash %= outer_relation->hash_table.bucket_count();
return hash;
}
}
- C++哈希表 - 如何解决自定义数据类型作为键的unordered_map冲突?
- 通过 lambda unordered_set自定义哈希
- std::tuple 的自定义哈希不适用于unordered_set
- 为自定义类C++实现哈希
- 自定义哈希表实现-将字符串映射到整数时出现内存错误
- 标准::C++ 中的无序列图中的自定义哈希
- 通过自定义结构和链接列表类中的C 中的哈希表
- 在自定义哈希表头文件中包括自定义链表
- 迭代器关系运算符出错(带单独链接和迭代器的自定义哈希表)
- C unordered_map自定义的哈希函数碰撞
- 为boost哈希映射定义自定义哈希函数
- 将哈希函数定义为结构的一部分
- C++:将自定义哈希键值从 unordered_map 输出到 std::cout 时出错
- C++:为unordered_set编写一个自定义哈希函数,该函数使用哈希表中的桶数
- 自定义无序集哈希函数
- 创建自定义哈希函数unordered_map时出现问题
- 当用户自定义哈希函数在 unordered_map 中时,无法解码 g++ 中模糊的编译器错误
- 这个自定义 md5 哈希算法是如何实现的
- 如何通过传递命名函数为unordered_set显式指定自定义哈希函数
- 正在对unordered_set的自定义指针类型进行哈希处理