hash_map:为什么它定义less而不是equal_to

时间:2010-10-25 19:59:11

标签: c++ data-structures stl

C ++,使用Visual Studio 2010.关于为什么用户定义的hash_map特征实际上需要总排序的问题。

我有一个简单的结构,比如FOO,它只有一些整数。我想使用hash_map这是一个哈希表,其键是无序,用于存储FOO的结构。我只需要快速搜索其相关值,所以这是一个正确的选择:hash_map<FOO, int32_t>

但是,我需要实现自己的哈希函数和FOO的一些比较函数。以下是hash_map的定义,取自MSDN:

template <
   class Key, 
   class Type, 
   class Traits=hash_compare<Key, less<Key> >, 
   class Allocator=allocator<pair <const Key, Type> > 
>
class hash_map

事实证明我需要实现hash_compare个仿函数:

template<class Key, class Traits = less<Key> >
   class hash_compare
   {
   Traits comp;
public:
   const size_t bucket_size = 4;
   const size_t min_buckets = 8;
   hash_compare( );
   hash_compare( Traits pred );
   size_t operator( )( const Key& _Key ) const; // This is a hash function
   bool operator( )(                            // This is an ordering function
      const Key& _Key1,
      const Key& _Key2
   ) const;
   };

以下是来自MSDN的bool operatod()的详细说明:

对于任何类型为Key的_Key1 在序列中 _Key2之前且具有相同的哈希值(哈希函数返回的值),hash_comp(_Key2,_Key1 )是假的。该函数必须对Key类型的值强加总排序

hash_compare提供的函数返回comp(_Key2,_Key1),其中comp是Traits类型的存储对象,可以在构造对象hash_comp时指定。对于默认的Traits参数类型less,排序键的值不会减少。

hash_compare编写FOO类很容易。对于询问如何实现类,这个问题。但是,对于我来说,为什么他们将默认特征参数设置为less<key>并且需要总排序并不是直截了当的。

hash_map无序数据结构。所以,我认为让equal_tonot_equal_to代替lessgreater就足够了。但是,MSDN的描述明确指出密钥是有序的,这让我感到困惑。

我是否误解了hash_map的定义?为什么STL的hash_map实际上需要其密钥的订单?

3 个答案:

答案 0 :(得分:3)

您正在查看的

hash_map是VS2003中的Microsoft扩展,实际上现在位于Visual C ++中的stdext - 它不是STL的一部分。

std::unordered_map是一个关联容器的官方 STL版本,可通过hashable键访问值 - 该谓词就像您预期的那样是相等的。

template<class Key,
    class Ty,
    class Hash = std::hash<Key>,
    class Pred = std::equal_to<Key>,
    class Alloc = std::allocator<std::pair<const Key, Ty> > >
    class unordered_map;

答案 1 :(得分:3)

  

对于类型为Key的任何值_Key1,在序列中 _Key2之前具有相同的哈希值(值   由散列函数返回),hash_comp(_Key2,_Key1)为false。该功能必须施加一个   关于Key类型值的总排序

具有相同散列值的密钥的总排序保证了散列到同一个桶的密钥的总排序。

这提供了更有效地实现搜索特定存储桶中的密钥的机会 - 例如Θ(log n)二分搜索是可能的。如果没有这样的保证排序,最坏的情况(许多不同的密钥都在同一个桶中,因为它们都散列到相同的值)是Θ(n)。

答案 2 :(得分:2)

hash_map的确切要求因实施而异,其中一些(如您所见)并没有多大意义。这就是为什么他们决定在TR1和/或C ++ 0x中包含hash_map(或hash_*)的部分原因。相反,他们有unordered_[multi](map|set),只需要equal_key,而不是operator<

结论:除非您有其他原因,否则请使用unordered_map代替hash_map