- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
#include <unordered_set>
#include <iostream>
class edge{
public:
float a1;
float a2;
};
struct comp{
bool operator()(const edge& e1, const edge& e2) const {
return true;
return (
(e1.a1==e2.a1 && e1.a2==e2.a2) ||
(e1.a1==e2.a2 && e1.a2==e2.a1)
);
};
};
struct hash{
size_t operator()(const edge& e1) const {
// return std::hash<float>()(e1.a1+e1.a2);
return std::hash<float>()(e1.a1+e1.a2*2);
};
};
int main() {
std::unordered_set<edge,hash,comp> s1;
s1.insert(edge{1.1,2.2});
s1.insert(edge{2.2,1.1});
for( auto& it : s1 ) {
std::cout << it.a1 << " " << it.a2 << "\n";
}
std::cout << "s1.size " << s1.size() << "\n";
}
我意识到如果不同的元素具有相同的散列值,那么它们被认为是相等的,但我只想让这个 unordered_set 使用我定义的比较器,而忽略散列?
如何实现?
我知道我可以使用set,但是使用set需要考虑顺序,如果a < b为真,b < a也为真,那么这个元素将不会插入成功,有时,很难提供顺序。
如果有人能帮忙,不胜感激
编辑:我的意图是让两条边称为 e1、e2,如果 (e1.a1==e2.a1&&e1.a2==e2.a2)
或 (e1.a1== e2.a2 && e1.a2==e2.a1)
正如我提供的在结构比较中。但是当我测试时。哈希函数似乎也可以改变比较。有人说我定义散列和比较器的方式会导致未定义的行为。真的吗?为什么?如果是真的,如何解决这个问题?我只希望比较器决定将哪个插入到 unordered_set 中而不重复。并且真的不关心哈希。
顺便说一句,感谢很多人的回复
最佳答案
如果你想处理edge.a1
和 edge.a2
可互换地,您必须实现一个哈希函数,即使它们被交换也能返回相同的值。我建议不要使用加法,因为 addition may not be commutative for floats ,但您可以按大小对它们进行排序,然后合并哈希值:
struct hash {
size_t operator()(const edge& e1) const {
auto h1 = std::hash<float>{}(std::min(e1.a1, e1.a2));
auto h2 = std::hash<float>{}(std::max(e1.a1, e1.a2));
return h1 ^ (h2 << 1)
};
};
这只对相当大的 float 集有意义,因为否则散列开销可能超过了首先使用散列数据结构的好处。
引用旧答案:
Objects with the same hash are not considered equal in
unordered_set
. They are just stored in the same bucket. There is aKeyEqual
template parameter for the comparison, which by default uses theoperator==
of yourKey
. So your main problem is, thatcomp
should implemente1 == e2
and note1 < e2
(and should probably be calledequal
).The hash is just used to speed up the search, insertion, and removal of elements.
On another note, you may want to use the hashes of the member variables instead of the values themselves to compute the hash of
edge
:struct hash {
size_t operator()(const edge& e1) const {
auto h1 = std::hash<float>{}(e1.a1);
auto h2 = std::hash<float>{}(e1.a2);
return h1 ^ (h2 << 1)
};
};This way, you won't get the same hash for two edges with swapped coordinates. This way of combining hashes is suggested here (but is not a good way to combine more than two).
关于c++ - cpp unordered_set 只使用比较器而不是散列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59156224/
我是一名优秀的程序员,十分优秀!