Ich möchte ein Element mit der Löschmethode aus einem Vektor löschen. Das Problem hierbei ist jedoch, dass das Element nicht garantiert nur einmal im Vektor vorkommt. Es kann mehrmals vorhanden sein und ich muss alle löschen. Mein Code ist ungefähr so:
void erase(std::vector<int>& myNumbers_in, int number_in)
{
std::vector<int>::iterator iter = myNumbers_in.begin();
std::vector<int>::iterator endIter = myNumbers_in.end();
for(; iter != endIter; ++iter)
{
if(*iter == number_in)
{
myNumbers_in.erase(iter);
}
}
}
int main(int argc, char* argv[])
{
std::vector<int> myNmbers;
for(int i = 0; i < 2; ++i)
{
myNmbers.push_back(i);
myNmbers.push_back(i);
}
erase(myNmbers, 1);
return 0;
}
Dieser Code stürzt offensichtlich ab, weil ich das Ende des Vektors ändere, während ich ihn durchlaufe. Was ist der beste Weg, um dies zu erreichen? Dh gibt es eine Möglichkeit, dies zu tun, ohne den Vektor mehrmals zu durchlaufen oder eine weitere Kopie des Vektors zu erstellen?
std::remove()
Verschiebt Elemente so, dass die zu entfernenden Elemente überschrieben werden. Der Algorithmus ändert die Größe des Containers nicht. Wennn
Elemente entfernt werden, ist nicht definiert, welchen
Elemente die letzten sind.Wenn Sie erase aufrufen, werden Iteratoren ungültig. Sie können Folgendes verwenden:
Oder Sie können std :: remove_if zusammen mit einem Funktor und std :: vector :: erase verwenden:
Anstatt in diesem Fall Ihren eigenen Funktor zu schreiben, können Sie std :: remove verwenden :
In C ++ 11 können Sie ein Lambda anstelle eines Funktors verwenden:
In C ++ 17 sind auch std :: experiment :: erase und std :: experiment :: erase_if verfügbar, in C ++ 20 werden diese (endgültig) in std :: erase und std :: erase_if umbenannt :
oder:
quelle
erase
mitremove
der kanonische Weg, dies zu tun.Sie können mit dem Indexzugriff iterieren.
Um die Komplexität von O (n ^ 2) zu vermeiden, können Sie zwei Indizes verwenden: i - aktueller Testindex, j - Index zum Speichern des nächsten Elements und am Ende des Zyklus neue Größe des Vektors.
Code:
In diesem Fall haben Sie keine Ungültigmachung von Iteratoren, die Komplexität ist O (n) und der Code ist sehr präzise und Sie müssen einige Hilfsklassen nicht schreiben, obwohl in einigen Fällen die Verwendung von Hilfsklassen in flexiblerem Code von Vorteil sein kann.
Dieser Code wird nicht verwendet
erase
Methode, sondern löst Ihre Aufgabe.Mit pure stl können Sie dies folgendermaßen tun (dies ähnelt der Antwort von Motti):
quelle
Abhängig davon, warum Sie dies tun, verwenden Sie ein std :: set möglicherweise eine bessere Idee als std :: vector.
Jedes Element kann nur einmal vorkommen. Wenn Sie es mehrmals hinzufügen, muss ohnehin nur eine Instanz gelöscht werden. Dies macht den Löschvorgang trivial. Die Löschoperation hat auch eine geringere zeitliche Komplexität als auf dem Vektor, jedoch ist das Hinzufügen von Elementen auf der Menge langsamer, so dass dies möglicherweise kein großer Vorteil ist.
Dies funktioniert natürlich nicht, wenn Sie daran interessiert sind, wie oft ein Element zu Ihrem Vektor hinzugefügt wurde oder in welcher Reihenfolge die Elemente hinzugefügt wurden.
quelle
Um das erste Element zu löschen, können Sie Folgendes verwenden:
quelle