2016-03-30 10 views
2

Ich lerne C++ und ich habe Probleme mit Zeigern auf Strukturen in Vektor gespeichert. Das Problem ist, dass ich die Struktur Student zweimal sortiert halten muss. Einmal durch die ID des Schülers und ein weiteres mal nach dem Namen des Schülers, so ist es leicht, die Werte darin zu suchen. Aus diesem Grund habe ich zwei Vektoren von Zeigern:Wie man Zeiger auf im Vektor gespeicherte Strukturen behält?

vector<Student *> sortedByID;  
vector<Student *> sortedByName; 

Die Struktur sieht wie folgt aus, und ich halte es auch in Vektor (obwohl es wahrscheinlich keine gute Idee ist):

struct Student { 
    int id; 
    string name; 
}; 

vector <Student> students; 

I Ich erstelle die neue Struktur mit push_back und fülle sie mit Parametern aus einer Funktion (ja, ich habe einen Konstruktor). Damit der Vektor von Zeigern sortierte Ich bin mit lower_bound wie unten dargestellt:

students.push_back(Student(id, name)); 
it = lower_bound(sortedByID.begin(), sortedByID.end(), id, cmp()); 
sortedByID.insert(it, &(students.back())); 
//the same for name 

Das Problem ist, dass jedes Mal wenn ich die Struktur mit push_back fügen Sie neuen Vektor reallocs und zerstören die Adresse der vorherigen Objekte, so Zeiger im Vektor sortedByID Zeigen Sie auf ungültigen Wert. Ich denke, es wäre das gleiche mit einem Array von Strukturen, denn sobald das Array voll ist, gibt es keinen anderen Weg (so weit ich weiß), die Größe zu ändern, als ein neues Array zu erstellen und alle Daten aus dem vorherigen Array zu kopieren (Die Adresse ändert sich also wieder).

Gibt es einen cleveren Weg, dieses Problem zu lösen? Bitte beachten Sie, dass ich nur Vektor und keine anderen Behälter von STL verwenden darf.

+5

Sie können nicht, gehen Sie eher mit Indizes für diesen Fall. Diese werden sich nicht ändern, selbst wenn der Vektor sein internes Array neu zuordnet. –

+2

Sie können die sortierten Vektoren Vektoren von Ganzzahlen machen, die in "Studenten" indexieren. Natürlich müssen Sie dann sicherstellen, dass Sie nicht aus der Mitte von "Studenten" entfernen, ohne Ihre Sortierung neu zu berechnen. –

+0

Sie dürfen nur 'vector' verwenden, oder? Scheint nicht wie ein echtes Weltproblem, oder? : rolleyes: – mainactual

Antwort

2

Es gibt drei Möglichkeiten, dieses Problem nur mit Vektoren und keine anderen Behälter zu lösen:

1) Vermeiden Sie die Neuzuteilung. Dies kann nur erreicht werden, wenn Sie das maximale M der erwarteten Anzahl von Elementen kennen, die in Ihren Vektor eingefügt werden sollen. In diesem Fall können Sie students.reserve(M);.

2) Vergessen Sie die Zeiger für sortedByID und sortedByName. Verwenden Sie Ganzzahlen (oder besser gesagt size_t) Speichern Sie den Index eines Schülers in anstelle eines Zeigers. Dies setzt natürlich voraus, dass die Reihenfolge der Gegenstände in den Schülern nie geändert wird.

3) Speichern Sie nicht die Schüler selbst in einem Vektor, sondern machen einen Vektor von Zeigern zu Studenten (unsortiert), die aus freien Speicher zugeordnet sind. Wenn diese Alternative alle Ihre Kriterien erfüllt, würde ich empfehlen, anstelle von rohen Zeigern shared_ptr<Student> zu gehen.

+0

1) Ich weiß nicht die endgültige Anzahl der Elemente in der Struktur, aber es gibt Tausende von ihnen.2) Ich könnte versuchen, es so zu machen, aber es ist nicht garantiert, dass einige der Schüler nicht gelöscht werden (ich würde sagen, dass es garantiert ist, dass sie ... sein werden). Also muss ich einen Weg finden, wie ich die Struktur erneut überprüfen und sortieren kann. Die Idee dahinter war, sie so zu sortieren, dass eine binäre Suche möglich wäre. Ich muss relativ schnell mit den Werten in der Struktur arbeiten (max O (log n)). – Filco28

+0

Wenn Sie Ihre Datenstruktur in einer Klasse kapseln, können Sie das Löschen steuern und sich vorstellen, Studenten in einer anderen Reihenfolge als sequenziell einzufügen. Die Verwendung von Indizes würde dies sehr nützlich machen, da in den sortierten Vektoren leicht die zu entfernenden Indizes und die anzupassenden Indizes gefunden werden können. – Christophe