Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用带有自定义结构的无序_集?_C++_C++11_Struct_Set_Unordered Set - Fatal编程技术网

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); };