【问题标题】:Why doesn't boost::hash_value support boost::unordered_set by default?为什么 boost::hash_value 默认不支持 boost::unordered_set?
【发布时间】:2013-11-18 03:09:48
【问题描述】:

一个人应该能够使用集合的集合似乎很直观,实际上std::set 被设计为默认支持这种使用(因为默认实现了字典顺序。)同样,期待相同的功能似乎是合理的的boost::unordered_set。默认情况下 boost 没有为boost::unordered_set 实现通用哈希函数是否有充分的理由,例如:

// DEFINE A HASH FUNCTION FOR A HASH-SET THAT COMBINES THE HASH VALUES
// OF THE ELEMENTS OF THAT SET
namespace boost {
    template<typename T>
    size_t hash_value(const boost::unordered_set<T> & set) {
        typename boost::unordered_set<T>::const_iterator it, itend;
        size_t seed = 0;
        for ( it = set.begin(), itend = set.end(); it != itend; it++ ){
            boost::hash_combine(seed,boost::hash_value(*it));
        }
        return seed;
    }
}

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    通常,您希望哈希值很快,最好是恒定时间。

    string 上,您可以做的一件事是获取长度,然后仅在其长度上采样 X 次(假设非病态输入,这将非常适合避免冲突)。

    unordered_set 缺少get_nth,这将允许类似的策略将散列时间降低到 O(1)。或者,unordered_set 可以保留其内容散列的异或并将其用作自己的散列(不是 hash_combine,因为这取决于顺序,并且当有 100 个元素时,很难从组合散列中删除第三个元素在 O(1) 时间内)。

    由于缺乏良好的 O(1) 实现,默认公开 hash_valueunordered_set&lt;unordered_set&lt;foo&gt;&gt; 的构建者来说似乎过于令人鼓舞,而实际上他们应该编写 unordered_set&lt; my_unordered_set_wrapper&lt;foo&gt; &gt;,其中 unordered_set_wrapper 执行上述“xor”内容散列”以产生 O(1) hash_value。要么,要么扩展unordered_set

    至于为什么boost 实际上 没有包含它,您必须询问所有曾经向boost 添加内容的人。他们似乎不存在。

    【讨论】:

    • 字符串散列的问题是,病态输入确实会发生,例如地址只有一个字符不同。默认情况下作弊是要求它。
    • 我上面建议的散列函数会不会因为散列组合依赖于顺序而不起作用?
    • @ldog unordered_set 上的累积哈希的想法是 O(1) 将在添加或删除项目时更新它。制作这个 O(1) 的最简单方法是使其成为内容哈希的对称异或。这通常是个坏主意,因为您希望“abc”的哈希值与“bad”不同,但在集合或unordered_set 中,添加/删除元素的顺序对集合的状态没有意义。
    • @Yakk 好的,我知道存在效率问题,但我建议的哈希函数是否可以工作?
    • @ldog 现在我想起来了,可能不会。为了使您的解决方案起作用,您必须对一组比较相等/具有相同哈希的固定元素有一个固定的顺序。我怀疑您的unordered_set 将有不同的顺序,具体取决于哈希表的大小和/或两个元素发生哈希冲突时的插入顺序(因为它只有== 和通常对它们进行排序的哈希结果...)。您必须对其进行测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-28
    • 2011-04-28
    • 2021-03-02
    相关资源
    最近更新 更多