std :: unordered_map中的键与哈希

时间:2019-01-13 16:14:11

标签: c++ hashmap containers

我经常需要一个将散列与任意对象相关联的容器(理论上,如果两个不同的对象具有相同的散列,则可能发生冲突)。

在C ++ 98中,我将使用template<class Key, class T> class std::mapKey作为在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 ++中,是否有一个内置容器使用哈希并具有基于这些哈希的查找接口?

2 个答案:

答案 0 :(得分:2)

您有一个映射,而不是一个哈希映射;您的密钥是哈希的事实与容器无关。

关于唯一的显着特征是您很少关心哈希的顺序;所以无序地图可能是最好的。

采用旧解决方案,将地图替换为无序地图,将less操作替换为equal,并将哈希值(可能向下)替换为64位。例如,经典指针哈希仅为reinterpret_cast<unit_ptr>( key )

答案 1 :(得分:2)

最初unordered_map被称为hash_map,然后ISO C ++委员会明智地将其重命名,因为std::mapstd::unordered_map之间的重要区别不是 第一个使用二进制树,而第二个使用哈希树,但是,第一个是有序的,而后者则保证了恒定的时间复杂度。

因此std::unordered_map在内部使用哈希的事实只不过是实现细节:如果密钥是自定义类型,您只需要提供std::hash专业化名称(并且密钥很少是自定义类型)。除此之外,您应该忘记此容器的内部哈希值。

尽管有一些注释,但是如果您的关键是哈希,那么C ++ 98的实现绝对没有错。您可以继续在C ++> = 11中使用它,并在可能的情况下将其更新和使用新的语言工具。