2017-02-21 42 views
2

我想要做的是使我可以使用std :: unordered_set與我自定義類Vector2 - 包括可能性搜索已經在集合中的這種類的對象。設置一個自定義類用於無序設置元素不能在設置中找到

讓我來提供更多細節。我的課Vector2,包括自定義哈希表的標題,如下:

Class Vector2 
{ 
private: 
    static int lastID; 
    const int id; 
    int x; 
    int y; 

public: 
    Vector2(int _x, int _y); 
    ~Vector2(); 

    bool Vector2::operator==(const Vector2& other) const; 

    int getId() const; 
    int getX() const; 
    int getY() const; 
}; 

namespace std 
{ 
    template<> 
    struct hash<Vector2> 
    { 
     size_t 
      operator()(const Vector2& obj) const 
     { 
      return hash<int>()(obj.getId()); 
     } 
    }; 
} 

等類的memeber功能的實現很簡單:

int Vector2::lastID = 0; 

Vector2::Vector2(int _x, int _y) : id(lastID++) 
{ 
    x = _x; 
    y = _y; 
} 

int Vector2::getId() const 
{ 
    return id; 
} 

int Vector2::getX() const 
{ 
    return x; 
} 

int Vector2::getY() const 
{ 
    return y; 
} 

bool Vector2::operator==(const Vector2& other) const 
{ 
    if (x != other.x || y != other.y) return false; 
    return true; 
} 

然後,我的主要功能看起來像以下內容:

std::unordered_set<Vector2> mySet; 
mySet.insert(Vector2(1, 2)); 
mySet.insert(Vector2(3, 11)); 
mySet.insert(Vector2(-5, 0)); 

Vector2 whatToLookFor(1, 2); 
if (mySet.find(whatToLookFor) != mySet.end()) 
{ 
    std::cout << "Found it!" << std::endl; 
} 
else 
{ 
    std::cout << "Nothing found." << std::endl; 
} 

然而,儘管我希望可以將輸出爲Found it!,它實際上是Nothing found。這意味着,雖然Vector2對象Vector2(1, 2),Vector2(3, 11)Vector2(-5, 0)被插入到mySet中,但是當它們在這樣的集合內搜索時,它們以後未找到。

我在做什麼錯?

+0

你正在執行'hash'錯誤。我們要求,如果'a == b',那麼'hash(a)== hash(b)'。 – kennytm

+0

除了SingerOfTheFalls答案,請注意'Vector2'的複製構造函數將創建另一個具有相同ID的'Vector2'對象。這可能是也可能不是你想要的。 –

+0

@MartinBonner感謝您指出這一點!的確,在我的理想情況下,所有具有相同'x'和相同'y'的Vector2'對象將具有相同的'id',但我想這對於這種特殊情況來說並不重要,對吧? – Andy

回答

3

unordered_set中的搜索操作在很大程度上取決於元素的哈希值,要求給定散列函數h:if A == B,然後h(A) == h(B)

執行搜索時,散列函數用於確定元素所屬的存儲區。之後,如果存儲桶中有多個元素,則會執行附加檢查以將這些元素相互比較。這可以通過直接比較元素,再次重新哈希或使用其他技術來完成。

您的課程有兩個數據成員,顯然您希望通過這些確切成員「查找」一個元素(即您期望如果A.x == B.x && A.y == B.y,則A == B,反之亦然)。然而,你的散列函數只基於元素的id哈希值,而忽略其他成員,這就是爲什麼它不能像你期望的那樣工作。

解決方案將重寫您的哈希函數以利用字段的值。您也可以檢查this文檔頁面。

+0

這正是我想找到的。所以,我不明白以下幾點。在我的哈希重載中,不是返回'obj.getId()',我想我可以返回一個我真正感興趣的對象屬性的組合 - 'x'和'y'。但是,我如何保證這種組合的獨特性?我見過類似'return obj.getX()+ obj.getY()'的例子,但似乎不足 – Andy

+0

@Andy,我相信有多種方法可以實現這一點,但我覺得這更像是一個數學問題比編程問題。無論如何,你可能會找到答案[這](http://stackoverflow.com/questions/919612/mapping-two-integers-to-one-in-a-unique-and-deterministic-way)有用的問題。 – SingerOfTheFall

+2

你的描述不太對。 'unordered_set'要求'A == B'意味着'h(A)== h(B)'(OP沒有)。 'h(A)== h(B)''不*暗示'A == B'(計數器例子會是一個散列衝突 - 這對於性能來說是不幸的,但對正確性來說並不是災難性的)。 –