【问题标题】:Creating generic hashtables - C++创建通用哈希表 - C++
【发布时间】:2010-12-04 22:37:57
【问题描述】:

.NET 框架有一个 Dictionary 类,该类被实现为哈希表并提供恒定时间 (O(1)) 的数据检索。我正在寻找 C++ 中的类似实现。我知道 std::map 但在这个数据检索中需要对数时间。 C++中有没有好的哈希表实现可以在恒定时间内检索数据?

如果我自己编写,我将如何计算密钥的哈希码?像 .NET 一样,我想在类型上使用 GetHashCode() 方法。

template<typename TKey,typename TVal>
class Dictionary
{
public:
   void Add(TKey key, TVal val){
       int hashCode = key.GetHashCode();
       /* .... */
   }
}

如果我确实喜欢上面的方法并且给定的键类型没有 GetHashCode() 方法,编译器会抛出错误。但是当 key 是 int 这样的原始类型时,此方法将不起作用。我可能需要通过提供 GetHashCode 来为 int 编写一个包装器。

我想知道 C++ 的实现方式是什么?

有什么想法吗?

【问题讨论】:

    标签: .net c++ algorithm hashtable


    【解决方案1】:

    如果您正在寻找即用型实现,那么除了 STL/TR1 和 Boost 哈希图之外,还有 google-sparsehash(它包含两种实现——一种针对空间进行了优化,一种针对速度进行了优化)。

    如果你想自己写,那么GetHashCode 可以实现为一个单独的仿函数,例如

    template < typename TKey, typename TValue, typename THash = someDefaultHash<TKey> >
    class Dictionary
    {
    public:
       void Add(TKey key, TVal val){
           int hashCode = THash()(key);
           /* .... */
       }
    }
    

    SGI's hash_map 就是这样做的。

    【讨论】:

    • 感谢您的回复。这看起来很有希望。我会试一试的。
    【解决方案2】:

    假设您使用 VS 2008 并安装了 Feature Pack 或 Service Pack 1,那么您有一个 TR1 的实现,其中包括 TR1::unordered_map。

    OTOH,除非您真的在创建一个 巨大 集合,否则 std::map 可能会比您预期的更具竞争力。在我的测试中,两者几乎打成平手是很常见的,而且 std::map 可以而且确实经常出现得更快。

    【讨论】:

    • 事实上,std::vector&lt;std::pair&lt;K,V&gt; &gt; 经常与std::map&lt;K,V&gt; 竞争。我认为 Meyers 的“Effective STL”书 (amazon.com/gp/product/0321334876) 中有一个项目。
    • 有,但它只在相当特定的情况下竞争。对于快速查找,必须对向量进行排序。如果事情分阶段工作,它会很好地工作,您收集所有数据,然后您可以对其进行排序,然后进行搜索(但很少在排序后插入或删除)。如果你混合插入、删除和搜索,像 map 这样的东西会更好。
    • @Jerry:是的,你总结得很好。
    【解决方案3】:

    也许,std::hash_map

    请注意,这不是标准 STL 库规范的一部分,但通常可用。它位于 MS 库和 SGI 库(如链接所示)和 STLport 中。

    【讨论】:

    • 虽然不是真正的标准,但过去 5 年几乎每个编译器都实现了一个(尽管 MSVC 和 G++ 的语义略有不同。)应该优先使用 unordered_map 或等效的 boost 容器。
    【解决方案4】:

    如果您手头没有 TR1 实现,boost::unordered_map 可能是您目前最好和最广泛可移植的解决方案。

    【讨论】:

      【解决方案5】:

      此外,如果需要严格遵守 C++ 标准,请查看 C++ Technical Report 1 以获取 std::tr1::unordered_map

      实际上std::hash_map 不是 C++ 标准,但无论如何都被广泛使用。

      【讨论】:

      • 请注意,有两个不同版本的(非标准)std::hash_map。我会使用std::tr1::unordered_map,它一定会成为下一个标准版本的std::unordered_map
      • std::hash_map 是一个 SGI 扩展。它也可以在 G++ 中使用,但在不同的命名空间中(我相信是__gnu_cxx)。
      • 但也有一个 Dinkumware 版本。 (我认为它现在位于 stdext 命名空间或类似名称空间中,但它曾经位于 std 命名空间中,因此它们的库的版本在那里。)
      【解决方案6】:

      在 C++ 中,您可以将具有哈希函数的函子的类型作为类型参数传递给模板。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-23
        • 2015-09-24
        • 1970-01-01
        • 1970-01-01
        • 2017-05-06
        • 2013-12-20
        • 1970-01-01
        • 2012-01-02
        相关资源
        最近更新 更多