我经常需要一个将散列与任意对象相关联的容器(理论上,如果两个不同的对象具有相同的散列,则可能发生冲突)。
在C ++ 98中,我将使用template<class Key, class T> class std::map
和Key
作为在T
上计算的哈希值:
struct object;
typedef std::string object_hash;
object_hash compute_hash(const object& obj);
std::map<object_hash, object> hash_map;
object_hash insert_or_assign(const object& obj)
{
object_hash hash = compute_hash(obj);
hash_map[hash] = obj;
return hash;
}
std::pair<bool, object> get_at(const object_hash& hash)
{
std::map<object_hash, object>::iterator iter = hash_map.find(hash);
if( iter == hash_map.end() )
return std::pair<bool, object>(false, object());
else
return std::pair<bool, object>(true, iter->second);
}
但是从C ++ 11开始,我们已经对容器进行了哈希处理,所以我期望像这样:
template<class T, class Key = std::hash<T>> class std::hashed_map
需要为类型std::hash
提供自定义T
,但是我们有
template<class Key, class T, class Hash = std::hash<Key>> class unordered_map
这不适用于我的情况,即键本身是哈希,并且没有与该任意对象相关的其他“键”概念。
类似于我的预期:
template<class Key, class Hash = std::hash<Key>> class unordered_set
但是没有基于哈希的查找功能。
在现代C ++中,是否有一个内置容器使用哈希并具有基于这些哈希的查找接口?
答案 0 :(得分:2)
您有一个映射,而不是一个哈希映射;您的密钥是哈希的事实与容器无关。
关于唯一的显着特征是您很少关心哈希的顺序;所以无序地图可能是最好的。
采用旧解决方案,将地图替换为无序地图,将less
操作替换为equal
,并将哈希值(可能向下)替换为64位。例如,经典指针哈希仅为reinterpret_cast<unit_ptr>( key )
。
答案 1 :(得分:2)
最初unordered_map
被称为hash_map
,然后ISO C ++委员会明智地将其重命名,因为std::map
和std::unordered_map
之间的重要区别不是 第一个使用二进制树,而第二个使用哈希树,但是,第一个是有序的,而后者则保证了恒定的时间复杂度。
因此std::unordered_map
在内部使用哈希的事实只不过是实现细节:如果密钥是自定义类型,您只需要提供std::hash
专业化名称(并且密钥很少是自定义类型)。除此之外,您应该忘记此容器的内部哈希值。
尽管有一些注释,但是如果您的关键是哈希,那么C ++ 98的实现绝对没有错。您可以继续在C ++> = 11中使用它,并在可能的情况下将其更新和使用新的语言工具。