2016-06-05 14 views
0
struct Room 
{ 
    int room; 
    int x,y; 
    int dist; 
    Room(){}Room(int _room,int xx,int yy,int _dist) 
    { 
     x = xx; 
     y = yy; 
     room = _room; 
     dist = _dist; 
    } 

    bool operator < (const Room& tempRoom)const 
    { 
     return dist < tempRoom.dist; 
    } 
}; 

int main() 
{ 
    set<Room>que; 
    que.insert(Room(0,0,0,1)); 
    que.insert(Room(0,0,0,1)); 
    que.insert(Room(1,2,0,1)); 
    que.insert(Room(0,2,0,1)); 
    for(auto itr = que.begin(); itr != que.end();itr++) 
     cout<<itr->room<<","<<itr->x<<","<<itr->y<<","<<itr->dist<<endl; 

    return 0; 
} 

Es zeigt den Ausgang 0,0,0,1. Aber es sollteKonnte Daten in std :: set nicht einfügen. Als Duplikat verworfen

0,0,0,1

1,2,0,1

0,2,0,1

sein Ich weiß, es ist etwas mit Operatorüberladung zu tun . Ich habe versucht, den Operator == zu überladen. Aber nach der Suche fand ich Set verwendet nur < Operator für jeden Vergleich. Wie ändere ich die überladene <-Funktion, um die obige Ausgabe zu erzielen? Vielen Dank.

+0

Wie wäre es mit in Ihrem 'operator <'? – CompuChip

+0

Zusätzlich zu den Antworten unten (die mehr oder weniger das Gleiche bedeuten), sollten Sie in Erwägung ziehen, ein separates Vergleichsobjekt für "Räume" zu implementieren - Sie wollen nicht wirklich, dass "room1 CompuChip

+0

@CompuChip: das ist eine schlechte Idee: die Logik, die Sie beschreiben, definiert _nicht_ eine streng schwache Ordnung. Sie müssten etwas nach "Raum

Antwort

2

Ihre aktuelle weniger als Betreiber hält nur das Feld dist. Die geordneten assoziativen Behälter betrachten zwei Objekte a und bäquivalent, wenn weder a < b noch b < atrue ergibt. Wenn bereits ein Element vorhanden ist, das einem eingefügten Objekt entspricht, wird die Einfügung ignoriert (und das return Ed-Paar zeigt auf das neue Element mit dem Element first und verwendet false im Element second, um anzuzeigen, dass kein Objekt eingefügt wurde).

Wenn Sie Ihr Objekt nur als äquivalent betrachten möchten, wenn alle Elemente gleich sind, verwenden Sie einen less-than-Operator, der alle Elemente berücksichtigt. Der einfachste Weg ist zu tun, um ein temporäres std::tuple nutzen, um ihr verwenden weniger als Betreiber:

bool Room::operator< (Room const& tempRoom) const { 
    return std::tie(this->x, this->y, this->room, this->dist) 
     < std::tie(tempRoom.x, tempRoom.y, tempRoom.room, tempRoom.dist); 
} 

Dieser Vergleichsoperator des Element der weniger als Betreiber verwendet die Reihenfolge eines Aggregat der Elemente zu bestimmen. Sie können auch jeden anderen Vergleich verwenden, sofern er eine streng schwache Ordnung definiert.

+0

Vielen Dank für die Erklärung, wie Set Check zwei Elemente gleich sind oder nicht. Ich habe eine andere Frage.Wenn ich ein spezifisches Element mit den drei Mitgliedsvariablen x, y und _room_, aber nicht mit _dist_ finden möchte, wie mache ich das? Die Funktion set :: find verwendet auch den Tahlil

+1

@Tahlil: Ich denke, das ist in der Tat eine andere Frage. Der grundlegende Ansatz würde die "lower_bound()" - und "upper_bound()" - Mitglieder des "std :: set <...>" mit geeigneten Schlüsseln verwenden, d. H. Einen minimalen/maximalen Wert für "dist". Abhängig von Ihren Bedürfnissen kann es sinnvoll sein, eine Klasse zu erstellen, die beim Einfügen nur den jeweiligen Mindestwert beibehält. In diesem Fall würden die Schlüssel nur alle "dist" -Mitglieder vergleichen (und es kann sinnvoll sein, eine 'std :: map <...>' mit einem Schlüssel zu verwenden, der das 'dist' nicht enthält und das' dist' macht der Wert der Karte). –

3

Sie vergleichen nur durch dist, so 2 Objekte mit dem gleichen dist werden gleich sein. Um diesen Vergleich durch all die Dinge zu beheben, die ein Objekt anders machen.

Etwas wie folgt aus:

bool operator < (const Room& lhs, const Room& rhs) 
{ 
    return 
     std::tie(lhs.dist, lhs.room, lhs.x, lhs.y) < 
     std::tie(rhs.dist, rhs.room, rhs.x, rhs.y); 
} 

Als Nebenwirkung habe ich ein Nicht-Mitglied-Funktion für den Vergleichsoperator.

2

Um in einem Satz als nützlich Ihre operator < Bedürfnisse alle relevanten Felder zu berücksichtigen, nicht nur die dist:

bool operator < (const Room& other)const { 
    return 
     dist < other.dist 
    || (dist == other.dist && room < other.room) 
    || (dist == other.dist && room == other.room && x < other.x) 
    || (dist == other.dist && room == other.room && x == other.x && y < other.y); 
}