Gibt es eine Möglichkeit, die Elemente in multiset oder unordered_set zu durchlaufen, während Elemente in c ++ gelöscht und eingefügt werden? - c++ - Program QA

Gibt es eine Möglichkeit, die Elemente in multiset oder unordered_set zu durchlaufen, während Elemente in c ++ gelöscht und eingefügt werden?

2020-06-30 c++ unordered-set multiset

Ich möchte jedes Element im Multiset oder unordered_set durchlaufen und während der Schleife das Element einfügen und entfernen. Beispielsweise:

unordere_set<int> myset = { 1, 2, 3, 4 };
for (auto it = myset.begin(); it != myset.end(); ++it) {
    myset.erase(*it);
    // do something that needs to use the set without *it like in a recursion function that takes the reference of the set
    myset.insert(*it);      
}

Ich möchte keine Kopie des Sets erstellen, da das Set sehr groß sein kann und nicht sehr effizient ist.

Answers

Ich sehe kein Problem mit diesem Code (allerdings nicht getestet)

unordered_set<int> myset = { 1, 2, 3, 4 };
for (auto it = myset.begin(); it != myset.end(); ) {
    auto save = *it;
    it = myset.erase(it);
    // do something that needs to use the set without *it like in a recursion function that takes the reference of the set
    myset.insert(save);      
}

Meine Argumentation ist , dass mysave.insert(save) sollte den Iterator nicht ungültig macht it , weil es wird nicht dazu führen Wiederkäuen des unordered_set, da alles , was Sie tun , ein Element hinzufügt zurück , die zuvor gelöscht wurde. Aber natürlich hängt es genau davon ab, was Sie tun // do something ...

Vermeiden Sie das Einfügen und Löschen beim Durchlaufen. Hier ist ein schlechter Vorschlag.

#include <vector>
#include <unordered_set>
using namespace std;

int main() {
  unordered_set<int> s { 1, 2, 3, 4, 5, 6, 7 };
  vector<unordered_set<int>::const_iterator> s_add;
  vector<unordered_set<int>::const_iterator> s_del;
  for (auto itr = s.begin(); itr != s.end(); ++itr) {
    // Some conditions
    s_add.push_back(itr);
    // Some conditions
    s_del.push_back(itr);
  }

  for (auto itr : s_add) {
    s.insert(*itr);
  }

  for (auto itr : s_del) {
    s.erase(itr);
  }

  return 0;
}

Nach dem cpprefrence kann Einfügung alle Iteratoren über beeinflussen unordered_set Behälter.

Wenn aufgrund des Einfügens ein erneutes Aufwärmen erfolgt, sind dies alle Iteratoren ungültig gemacht. Andernfalls sind Iteratoren nicht betroffen. Referenzen gibt es nicht ungültig gemacht. Das Aufwärmen erfolgt nur, wenn die neue Anzahl von Elementen vorhanden ist größer als max_load_factor()*bucket_count() .

Wenn die Einfügung ist erfolgreich, Zeiger und Verweise auf das dabei erhaltene Element wird im Knotenhandle gehalten, werden ungültig gemacht und Zeiger und Verweise auf dieses Element, bevor es extrahiert wurde, werden gültig.

Ich habe mich gefragt, ob Sie nur über einen Container iterieren und einige Einfüge- / Löschvorgänge ausführen möchten. Warum verwenden Sie nicht einfach std::vector Container- und Elementindizes, um sie einzufügen / zu löschen?

Wenn Sie darauf bestehen, unordered_set , können Sie std::next in einer while Schleife verwenden, um über Ihren unordered_set Container zu iterieren und einen Einfüge- / Löschvorgang durchzuführen.

Beachten Sie, dass der Wiederaufbereitungsalgorithmus nicht ausgelöst wird, da Sie dasselbe Element am Ende der Schleife einfügen.

unordered_set<int> myset = { 1, 2, 3, 4 };
unordered_set<int>::iterator it = myset.begin();
int i = 0;

while (it != myset.end()) {

    myset.erase(*it);
    // do something that needs to use the set without *it like in a recursion function that takes the reference of the set
    myset.insert(*it);
    it = next(myset.begin(), ++i);
}

Related