2017-02-21 6 views
2

내가하려는 것은 std :: unordered_set을 사용자 정의 클래스 Vector2 - 과 함께 사용하는 것이 가능하도록하는 것입니다 이미 집합에 속한 클래스의 객체를 검색하려면.정렬되지 않은 set 요소에 사용할 사용자 정의 클래스를 설정하는 것이 집합에서 찾을 수 없습니다

좀 더 자세히 알려 드리겠습니다. 사용자 정의 해시 테이블을 포함하여 내 수업 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()); 
     } 
    }; 
} 

같은 클래스의 일원이 기능의 구현은 간단하다 :

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에 삽입되지만 나중에 해당 세트 내에서 검색 할 때 발견되지 않습니다.

내가 뭘 잘못하고 있니? 다음 h(A) == h(B)A == B 경우, 일 : unordered_set

+0

'해시'를 잘못 구현하고 있습니다. 'a == b'이면'hash (a) == hash (b)'가 필요합니다. – kennytm

+0

SingerOfTheFalls는 "Vector2"의 복사 생성자가 동일한 ID를 가진 또 다른'Vector2' 객체를 생성한다는 점에 유의해야합니다. 그것은 당신이 원하는 것일 수도 아닐 수도 있습니다. –

+0

@MartinBonner 그 점을 지적 해 주셔서 감사합니다! 실제로, 이상적인 시나리오에서, 같은'x'와 같은'y'를 가진 모든'Vector2' 객체는 같은'id'를 가질 것입니다,하지만이 특별한 경우에는별로 중요하지 않다고 생각합니다. 맞습니까? – Andy

답변

3

검색 작업은 해쉬 함수 h 주어진 것을 요하는 요소의 해시 값에 크게 의존한다.

검색을 수행 할 때 해시 함수를 사용하여 요소가 속한 버킷을 결정합니다. 그런 다음 버킷에 여러 요소가있는 경우 이러한 요소를 서로 비교하기 위해 추가 검사가 수행됩니다. 이는 요소를 직접 비교하거나, 다시 해싱하거나, 다른 기법을 사용하여 수행 할 수 있습니다.

클래스에는 두 개의 데이터 멤버가 있으며, 정확한 멤버로 요소를 "찾을"것으로 예상됩니다 (즉, 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, 나는 그것을 달성하는 여러 가지 방법이 있다고 생각한다. 그러나 나는 그것이 수학과 비슷하다고 생각한다. 문제가 프로그래밍 문제보다. 어쨌든 [this] (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'를 암시하지 않습니다. (카운터 예제는 해시 콜리 전일 것입니다 - 성능면에서는 불행하지만 정확성에서는 대격변이 아닙니다.) –