【问题标题】:hash_map: why it defines less, rather than equal_tohash_map:为什么它定义less,而不是equal_to
【发布时间】:2010-10-25 19:59:10
【问题描述】:

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 operator() 的详细描述:

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

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

FOO 编写hash_compare 类很容易。这个问题不是询问如何实现一个类。但是,对我来说,为什么它们的默认 trait 参数为 less&lt;key&gt; 并需要总排序对我来说并不简单。

hash_map 是一个 无序 数据结构。所以,我认为拥有equal_tonot_equal_to 而不是lessgreater 就足够了。但是,MSDN 的描述明确指出键是有序的,这让我感到困惑。

我是不是误解了hash_map的定义?为什么 STL 的 hash_map 实际上需要它的 key 的命令?

【问题讨论】:

    标签: c++ data-structures stl


    【解决方案1】:

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

    具有相同哈希值的键的总排序保证了哈希到同一个桶的键的总排序。

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

    【讨论】:

    • 我认为这样的总排序对搜索没有帮助。这是因为 1) 哈希函数应该是统一的,并且 load_factor
    • @Chang,除非您提前知道所有可能的密钥,否则无法保证每个插槽一个元素 - 事实上,一种 DOS 攻击使用哈希函数的知识来故意产生冲突。不,它明显会减慢插入速度。
    【解决方案2】:

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

    std::unordered_map 是关联容器的官方 STL 版本,通过可散列键访问值 - 正如您所期望的那样,它的谓词是相等的。

    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;
    

    【讨论】:

      【解决方案3】:

      hash_map 的具体要求因实现而异,其中一些(如您所见)并没有多大意义。这也是他们决定在 TR1 和/或 C++0x 中包含hash_map(或hash_*)的部分原因。相反,他们有unordered_[multi](map|set),它只需要equal_key,而不需要operator&lt;

      底线:除非您有真正突出的理由不这样做,否则请使用unordered_map 而不是hash_map

      【讨论】:

      • +1 以获得有趣的历史课,但我认为它并不能完全回答问题......
      • 谢谢!是的,我应该使用 unordered_map。我想知道 hash_map over map 和 unordered_map 有哪些独特的功能。
      • @minjang:map 是有序的(通常实现为平衡树),因此它支持在范围内查找项目等事情。 unordered_map 给出 O(1) 插入/删除/查找。 hash_map 与 unordered_map 类似,但没有规范可遵循,因此不同的版本有不同的功能、要求等。
      猜你喜欢
      • 2011-04-10
      • 2011-10-25
      • 1970-01-01
      • 2022-08-19
      • 1970-01-01
      • 1970-01-01
      • 2012-07-19
      • 2021-04-26
      • 1970-01-01
      相关资源
      最近更新 更多