简体   繁体   English

std :: unordered_map中的键与哈希

[英]key vs. hash in a std::unordered_map

I often need a container where an hash is associated to an arbitrary object (collisions are theoretically possible if two different objects have the same hash). 我经常需要一个将哈希与任意对象相关联的容器(理论上,如果两个不同的对象具有相同的哈希,则可能发生冲突)。

In C++98 I would use template<class Key, class T> class std::map using Key as the hash computed on T : 在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);
}

But starting from C++11 we have hashed containers so I expected something like: 但是从C ++ 11开始,我们已经对容器进行了哈希处理,所以我期望这样的东西:

template<class T, class Key = std::hash<T>> class std::hashed_map

with the requirement to provide a custom std::hash for type T , but instead we have 要求为类型T提供自定义std::hash ,但是我们有

template<class Key, class T, class Hash = std::hash<Key>> class unordered_map

which does not apply to my scenario where the key is the hash itself, and there is no other "key" concept related to the arbitrary object. 这不适用于我的情况,其中键是哈希本身,并且没有与该任意对象相关的其他“键”概念。

Similar to what I expected is: 与我预期的类似:

template<class Key, class Hash = std::hash<Key>> class unordered_set

but there are no lookup functions based on hash. 但是没有基于哈希的查找功能。

In modern C++ is there a built in container that uses hashes and has a lookup interfaces based on these hashes? 在现代C ++中,是否存在使用哈希的内置容器,并具有基于这些哈希的查找接口?

You have a map not a hash map; 您有一个映射而不是一个哈希映射; the fact your key is a hash is irrelevant to the container. 您的密钥是哈希的事实与容器无关。

About the only salient feature is that you rarely care about the order of hashes; 关于唯一的显着特征是您很少在乎哈希的顺序。 so unordered map is probably best. 因此无序地图可能是最好的。

Take your old solution, replace map with unordered map, replace less operstion with equal and a hash (possibly down) to 64 bits. 使用旧的解决方案,将地图替换为无序地图,将equal运算符替换为less操作,然后将哈希值(可能向下)替换为64位。 For example, the classic pointer hash is just reinterpret_cast<unit_ptr>( key ) . 例如,经典的指针哈希只是reinterpret_cast<unit_ptr>( key )

Originally the unordered_map was called hash_map , then the ISO C++ committee wisely renamed it, because the important difference between std::map and std::unordered_map is not that the first uses binary trees while the latter uses hashes, but that the first is ordered while the latter guarantees constant-time complexity. 最初, unordered_map称为hash_map ,然后ISO C ++委员会明智地将其重命名,因为std::mapstd::unordered_map之间的重要区别不是前者使用二叉树而后者使用哈希, 而是前者是有序的而后者保证了恒定的时间复杂度。

So the fact that std::unordered_map uses hashes internally is little more than an implementation detail: you only need to provide an std::hash specialization if the key is a custom type (and the key is unfrequently a custom type). 因此, std::unordered_map内部使用哈希的事实只不过是实现细节:如果是自定义类型(并且键很少是自定义类型),则只需要提供std::hash特殊化即可。 Apart from that, you should forget about the internal hashes of this container. 除此之外,您应该忘记此容器的内部哈希。

Despite some comments, if your key is the hash then there's absolutely nothing wrong with you C++98 implementation. 尽管有一些评论,但是如果您的键是哈希,那么C ++ 98实现绝对没有错。 You can keep using it in C++ >= 11, updating and tiding it to the new language facilities where possible. 您可以继续在C ++> = 11中使用它,并在可能的情况下将其更新和使用新的语言工具。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM