C++ 如何使用带有自定义结构的无序_集?
我想将C++ 如何使用带有自定义结构的无序_集?,c++,c++11,struct,set,unordered-set,C++,C++11,Struct,Set,Unordered Set,我想将无序集与自定义结构一起使用。在我的例子中,自定义struct表示欧几里德平面中的二维点。我知道应该定义散列函数和比较器运算符,我已经这样做了,正如您在下面的代码中所看到的: struct Point { int X; int Y; Point() : X(0), Y(0) {}; Point(const int& x, const int& y) : X(x), Y(y) {}; Point(const IPoint& ot
无序集
与自定义结构
一起使用。在我的例子中,自定义struct
表示欧几里德平面中的二维点。我知道应该定义散列函数和比较器运算符,我已经这样做了,正如您在下面的代码中所看到的:
struct Point {
int X;
int Y;
Point() : X(0), Y(0) {};
Point(const int& x, const int& y) : X(x), Y(y) {};
Point(const IPoint& other){
X = other.X;
Y = other.Y;
};
Point& operator=(const Point& other) {
X = other.X;
Y = other.Y;
return *this;
};
bool operator==(const Point& other) {
if (X == other.X && Y == other.Y)
return true;
return false;
};
bool operator<(const Point& other) {
if (X < other.X )
return true;
else if (X == other.X && Y == other.Y)
return true;
return false;
};
size_t operator()(const Point& pointToHash) const {
size_t hash = pointToHash.X + 10 * pointToHash.Y;
return hash;
};
};
结构点{
int X;
int-Y;
点():X(0),Y(0){};
点(常数int&x,常数int&y):x(x),y(y){};
点(常数i点和其他){
X=其他。X;
Y=其他。Y;
};
点和运算符=(常量点和其他){
X=其他。X;
Y=其他。Y;
归还*这个;
};
布尔运算符==(常数点和其他){
if(X==other.X&&Y==other.Y)
返回true;
返回false;
};
bool operatorstd::unordered_set的第二个模板参数是用于散列的类型。在您的情况下,它将默认为std::hash
,但不存在。因此,如果散列器是相同的类型,您可以使用std::unordered_set
或者,如果您不想指定散列器,请为点定义std::hash
的专门化,或者去掉成员函数并在专门化的操作符()的主体中实现散列,或者从std::hash专门化调用成员函数
#include <unordered_set>
struct Point {
int X;
int Y;
Point() : X(0), Y(0) {};
Point(const int& x, const int& y) : X(x), Y(y) {};
Point(const Point& other){
X = other.X;
Y = other.Y;
};
Point& operator=(const Point& other) {
X = other.X;
Y = other.Y;
return *this;
};
bool operator==(const Point& other) const {
if (X == other.X && Y == other.Y)
return true;
return false;
};
bool operator<(const Point& other) {
if (X < other.X )
return true;
else if (X == other.X && Y == other.Y)
return true;
return false;
};
// this could be moved in to std::hash<Point>::operator()
size_t operator()(const Point& pointToHash) const noexcept {
size_t hash = pointToHash.X + 10 * pointToHash.Y;
return hash;
};
};
namespace std {
template<> struct hash<Point>
{
std::size_t operator()(const Point& p) const noexcept
{
return p(p);
}
};
}
int main()
{
// no need to specify the hasher if std::hash<Point> exists
std::unordered_set<Point> p;
return 0;
}
#包括
结构点{
int X;
int-Y;
点():X(0),Y(0){};
点(常数int&x,常数int&y):x(x),y(y){};
点(常数点和其他){
X=其他。X;
Y=其他。Y;
};
点和运算符=(常量点和其他){
X=其他。X;
Y=其他。Y;
归还*这个;
};
布尔运算符==(常数点和其他)常数{
if(X==other.X&&Y==other.Y)
返回true;
返回false;
};
bool运算符当上述解决方案让您编译代码时,请避免使用点的哈希函数。有一个由b
参数化的一维子空间,y=-x/10+b
行上的所有点都将具有相同的哈希值。最好使用64位哈希函数,其中最上面的32位是x坐标和最下面的32位32位是y坐标(例如)
uint64_t hash(Point const & p) const noexcept
{
return ((uint64_t)p.X)<<32 | (uint64_t)p.Y;
}
uint64\u t散列(点常量&p)常量noexcept
{
return((uint64_t)p.X)我想通过提供更多的提示来扩展:
对于结构
,您不需要定义操作符=
或点(const Point&other)
,因为您(重新)实现了默认行为
通过删除if
子句,可以简化operator==
,如下所示:
unordered_set<Point> mySet;
bool operator==(const Point& other) { return X == other.X && Y == other.Y; };
struct Point {
int X, Y;
Point() : X(0), Y(0) {};
Point(const int x, const int y) : X(x), Y(y) {};
};
int main() {
auto hash = [](const Point& p) { return p.X + 10 * p.Y; };
auto equal = [](const Point& p1, const Point& p2) { return p1.X == p2.X && p1.Y == p2.Y; };
std::unordered_set<Point, decltype(hash), decltype(equal)> mySet(8, hash, equal);
return 0;
}
您的操作符anks@rmawatson中有一个错误!我决定使用第一个选项-指定哈希函数。对于所有新的无序关联结构来说都是非常新的,我肯定有很多东西要学习。
struct Point {
int X, Y;
Point() : X(0), Y(0) {};
Point(const int x, const int y) : X(x), Y(y) {};
};
int main() {
auto hash = [](const Point& p) { return p.X + 10 * p.Y; };
auto equal = [](const Point& p1, const Point& p2) { return p1.X == p2.X && p1.Y == p2.Y; };
std::unordered_set<Point, decltype(hash), decltype(equal)> mySet(8, hash, equal);
return 0;
}
auto hash = [](const Point& p) { return std::hash<int>()(p.X) * 31 + std::hash<int>()(p.Y); };