【问题标题】:Why C++ STL hash table (unordered_map) doesn't accept vectors as keys为什么 C++ STL 哈希表 (unordered_map) 不接受向量作为键
【发布时间】:2020-08-31 17:24:59
【问题描述】:

我认为这种设计选择背后是有原因的。 Boost seems to have an implementation for it,因此应该可以使用向量作为哈希表键。应用于数组的散列函数是否有任何理论属性使它们更容易发生冲突或其他不良行为?

【问题讨论】:

  • 我认为没有任何理由不能使用向量作为 unordered_map 的键;你只需要指定一个哈希函数来计算一个向量的哈希值。
  • 你能提供一个适合向量的哈希函数的例子吗?
  • 不是恒定的时间复杂度似乎可能会影响不将std::hash 专门用于std::vector 的决定,确保用户知道如果他们想使用他们会进入什么一个作为钥匙。不过,这是一个猜测。
  • 很好的观察@chris
  • 您需要为此滚动自己的哈希函数。一点都不难。

标签: c++ hash c++17 hashtable


【解决方案1】:

你会注意到 Boost 没有实际上有一个扩展来接受 vector<T> 作为一个专门的键 - 相反它有一个扩展可以让你使用任何 Iterable - 它生成哈希仅作为 Iterable 内容的函数...

这可能是可取的,也可能不是可取的,具体取决于:

  • 如果您想使用对象身份而不是对象值作为散列的基础......或者不。
  • 如果您对散列是一种非常量时间操作感到满意... 或者不。
    • 仅仅因为 boost::hash_range 似乎是 O(n) 并不意味着底层迭代不需要 5 分钟来返回每个调用的所有可哈希值...
  • 元素的顺序是否重要或不重要。
    • (我相信)将boost::hash_rangeboost::hash_combine 与两个不同但等效 unordered_set 对象之一使用会导致不同的哈希码,尽管它们的值等价。
  • 如果两个概念上不同的对象可以迭代相同的值(例如,vector<uint8_t> 表示数据缓冲区,或queue<SomeEnum>,其中SomeEnum : uint8_t 表示值队列)应该具有相同的 hahs 代码...与否。

怀疑STL背后的团队不喜欢上面描述的这么多上下文“如果”,这意味着提供默认行为是不明智的,所以他们要求您始终更明确地为任意对象生成哈希(此外,如果您想要 Boost 的行为,那么首先使用 Boost - 这不像 Boost 与 STL 竞争)。

另请参阅此 QA:C++ unordered_map using a custom class type as the key

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 2014-09-27
    • 2011-02-21
    • 2011-06-10
    相关资源
    最近更新 更多