例如,在下面的结构中:
1) editLine是指向具有CLRF的数据线的指针,
2) nDisplayLine为该editLine的显示行索引,
3) start是显示行中的偏移量,
4) len是文本的长度;
struct CacheKey {
const CEditLine* editLine;
int32 nDisplayLine;
int32 start;
int32 len;
friend bool operator==(const CacheKey& item1, const CacheKey& item2) {
return (item1.start == item2.start && item1.len == item2.len && item1.nDisplayLine == item2.nDisplayLine &&
item1.editLine == item2.editLine);
}
CacheKey() {
editLine = NULL;
nDisplayLine = 0;
start = 0;
len = 0;
}
CacheKey(const CEditLine* editLine, int32 dispLine, int32 start, int32 len) :
editLine(editLine), nDisplayLine(dispLine), start(start), len(len)
{
}
int hash() {
return (int)((unsigned char*)editLine - 0x10000) + nDisplayLine * nDisplayLine + start * 2 - len * 1000;
}
};现在我需要把它放到std::unordered_map<int, CacheItem> cacheMap_中
问题是如何为这种结构设计哈希函数,有什么指导原则吗?
如何确保散列函数是无冲突的?
发布于 2013-07-01 19:43:26
要创建哈希函数,可以使用std::hash,它是为整数定义的。然后,您可以像boost guys那样将它们组合在一起(因为做一个好的散列不是一件微不足道的事情),如下所述:http://en.cppreference.com/w/cpp/utility/hash。
下面是一个hash_combine方法:
inline void hash_combine(std::size_t& seed, std::size_t v)
{
seed ^= v + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}因此,“指南”或多或少是cppreference上显示的内容。
你不能确定你的散列函数是无冲突的。无冲突意味着您不会丢失数据(或者您将自己限制为您的类的一小部分可能性)。如果每个字段都允许任何int32值,则无冲突散列是一个非常大的索引,它不适合小的表。让unordered_map处理冲突,并按照上面的说明组合std::hash散列。
在您的例子中,它看起来像这样
std::size_t hash() const
{
std::size_t h1 = std::hash<CEditLine*>()(editLine);
//Your int32 type is probably a typedef of a hashable type. Otherwise,
// you'll have to static_cast<> it to a type supported by std::hash.
std::size_t h2 = std::hash<int32>()(nDisplayLine);
std::size_t h3 = std::hash<int32>()(start);
std::size_t h4 = std::hash<int32>()(len);
std::size_t hash = 0;
hash_combine(hash, h1);
hash_combine(hash, h2);
hash_combine(hash, h3);
hash_combine(hash, h4);
return hash;
}然后,您可以为您的类专门化std::hash操作符。
namespace std
{
template<>
struct hash<CacheKey>
{
public:
std::size_t operator()(CacheKey const& s) const
{
return s.hash();
}
};
}https://stackoverflow.com/questions/17402640
复制相似问题