什么是std :: unordered_set中的KeyEqual?

时间:2016-08-23 17:33:50

标签: c++ std c++-standard-library unordered-set

KeyEqual中第三个参数std::unordered_set的目的是什么?哈希的唯一性不够吗?

template<
    class Key,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator<Key>
> class unordered_set;

对不起,如果这个问题听起来很幼稚。从Python / PHP迁移到C ++:)

现在我的KeyEqual实现总是重复Hash impl。所以我很想知道我是否正确地做到了。

4 个答案:

答案 0 :(得分:3)

但是如果我们有哈希冲突怎么办?

enter image description here

该图片演示了两个不同的元素碰巧具有相等哈希值的情况。因此,当涉及散列时,散列值可能是唯一的。

引用> p + scale_x_discrete(limits = c("Cat1", "Cat2", "Cat3", "Cat4", "Cat5"), drop=FALSE)的{​​{3}}:

  

在内部,unordered_set中的元素未按任何方式排序   特定的顺序,但根据其哈希值组织成桶   允许直接快速访问单个元素的值   它们的值(平均时间复杂度恒定)。

所以一个桶可以有多个元素!这两个元素将具有相同的哈希值,但不保证是唯一的!

唯一保证唯一的是

答案 1 :(得分:2)

我们举个例子,一组带有散列函数的int s,只做一个简单的mod %操作

struct IntMod {
    constexpr std::size_t operator()(int i) const { return i % 10; }
};

std::unordered_set<int, IntMod> s;

这很容易导致哈希冲突,当发生这种情况时,您需要能够比较密钥以了解密钥是否已经存在。

s.insert(25);  // hash == 5
s.insert(35);  // hash == 5
assert(*s.find(25) == 25);  // both 25 and 35 are present despite the same hash
assert(*s.find(35) == 35);

如果我们添加一个只使用哈希函数的KeyEqual(就像你默认的那样建议),它会在第二次插入时中断。

struct IntEq {
  constexpr bool operator()(int a, int b) const {
    return IntMod{}(a) == IntMod{}(b);
  }
};

std::unordered_set<int, IntMod, IntEq> s;
s.insert(25);  // hash == 5
s.insert(35);  // hash == 5
assert(*s.find(25) == 25);
assert(*s.find(35) == 35);  // now this fails. s.find(35) returns iterator to 25

答案 2 :(得分:1)

很简单,该集需要知道两个键是否相等。 KeyEqual是实现这一目标的机制。

请记住,两个不能比较的密钥可以哈希到相同的值,并且该集需要能够检查它。

答案 3 :(得分:1)

不同的值不一定有不同的哈希值。例如,std::string的结果实际上有无限数量的std::size_t个对象,但只有2 ^ N std::hash<std::string>()(s)个对象,因此有些&#34;哈希冲突&#34;虽然算法试图让它们变得不可能,但这是不可避免的。

因此,std::unordered_setstd::unordered_map需要一种方法来测试元素是否相等或不相等,即使它们的哈希值相等。