set vs unordered_set für die Schnellste iteration
In meiner Anwendung habe ich folgende Anforderungen -
- Strukturierung der Daten aufgefüllt wird, einfach mal mit einigen Werten (keine Schlüssel/Wert-Paare).
Die Werte können wiederholt werden, aber ich möchte die Datenstruktur zum speichern von Ihnen nur einmal. - Werde ich Durchlaufen 100s von Zeiten, durch alle Elemente der Datenstruktur, die oben erstellt. Die Reihenfolge, in der die Elemente angezeigt werden, die in die iteration ist dabei unerheblich.
Constraint 1 deutet darauf hin, dass ich entweder mit set oder unordered_set, da die Daten nicht in form von Schlüssel-Wert-Paare.
Nun Einschub ist teurer als unordered_set einfügen, aber die Datenstruktur ist nur ausgefüllt, einmal am Anfang von meinem Programm.
Ich glaube, der entscheidende Faktor wird sein, wie schnell ich iterieren über alle Elemente der Datenstruktur. Ich bin mir nicht sicher, ob set oder unordered_set wird schneller sein für diesen Zweck. Ich glaube, der standard macht keine Erwähnung dieser Tatsache als dieser Vorgang wird O(n) für die Daten-Struktur. Aber ich Frage mich, für welche Datenstruktur iterator.next() schneller sein wird.
Wie wäre es mit einem vector?
Sie können verschiedene Strukturen für verschiedene Zwecke. Zum Beispiel, bauen eine
set
, dann sobald Sie fertig sind kopieren/verschieben und alles in eine vector
für die schnelle iteration. Also die Frage ist: brauchst du etwas andere als iteration, sobald es gefroren ist ? (wie schnell look-up)Sie denken, dass die Satz magisch nicht haben, diese Kosten zu bezahlen?
std::lower_bound
:-SInformationsquelleAutor Aviral Goel | 2014-07-01
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es mehrere Ansätze.
std::unordered_set
hat die SchnellsteO(1)
lookup/einfügen und dasO(N)
iteration (da hat jeder container). Wenn Sie Daten haben, die viel ändert, oder erfordert eine Menge von zufälligen lookups, dies ist wahrscheinlich die Schnellste. Aber test.O(N)
kopieren auf einestd::vector
gewinnen und aus angrenzenden Speicher-layout 100s von Zeiten. Testen, ob dies schneller ist als ein normalesstd::unordered_set
.boost::flat_set
bietet einestd::set
- Schnittstelle mit einemstd::vector
Speicher-back-end (D. H. einen zusammenhängenden Speicher-layout, das ist sehr cache - und prefetch-freundlich). Wieder, test, ob dieser gibt ein speed-up zu den anderen beiden Lösungen.Für die Letzte Lösung, finden Sie in der Boost Dokumentation für einige der Nachteile (es ist gut, sich bewusst zu sein, alle anderen Fragen wie die iterator-Aufhebungs -, move-Semantik und exception safety):
HINWEIS: mit schneller nachschlagen, es ist gemeint, dass eine
flat_set
hatO(log N)
auf zusammenhängenden Speicher anstattO(log N)
Zeiger jagt, die einer regelmäßigenstd::set
. Natürlich, einstd::unordered_set
hatO(1)
- lookup, der wird schneller für großeN
.Sie bedeuten schneller als
std::set
, die nichtO(log N)
Zeiger jagt, anstattO(log N)
binäre Suche auf zusammenhängenden SpeicherGut, als Sie sollten eine klärende Bemerkung zu diesem Effekt.
es ist ein Zitat aus der Boost-docs
scheint etwas übertrieben, wenn ein einfaches std::vector ist ausreichend.
InformationsquelleAutor TemplateRex
Ich würde vorschlagen, Sie verwenden entweder oder unordered_set für "filtration" und wenn Sie fertig sind, verschieben Sie die Daten in Vektor-fester Größe
unordered_set
ist eine schlechte option für die "filtration" im Vergleich zuset
. testen, ob ein einzelnes element ist, bereits dort ist die lineare Zeit.im Durchschnitt
unordered_set
ständige nachschlagen Komplexität, im Vergleich zu einer logarithmischen vonset
InformationsquelleAutor Michał Walenciak
Wenn Gebäude von der Daten-Struktur nicht Faktor in der performance-Probleme (oder zumindest nur am Rande), betrachten Sie die Speicherung Ihrer Daten in einer
std::vector
: Es gibt nichts, es zu schlagen.Für die Beschleunigung der ersten Gebäude von der Daten-Struktur, die Sie vielleicht zuerst einen insert in eine
std::unordered_set
oder zumindest eine für die überprüfung der Existenz vor dem einsetzen.Im zweiten Fall braucht es nicht enthalten die Elemente, konnte aber enthalten z.B. Indizes.
InformationsquelleAutor Deduplicator
Empfehle ich Ihnen nicht für die Verwendung in diesem Fall.
set
ist der binäre Baum, undunordered_set
ist hash-Tabelle - so viel Speicher verwenden, und haben langsam iteration Geschwindigkeit und schlechte Lokalität der Referenz. Wenn Sie die einfügen/entfernen/suchen von Daten Häufigset
oderunordered_set
gute Wahl, aber jetzt müssen Sie nur Lesen, speichern, Sortieren Sie die Daten einmal und verwenden Sie nur Daten viele Male.In diesem Fall sortiert Vektor werden kann, wie eine gute Wahl.
vector
ist dynamisch array, so hat es wenig overhead.Nur direkt, siehe code.
Das ist alles. Alle Ihre Daten bereit ist.
Wenn Sie brauchen, um Duplikate entfernen wie
set
, verwenden Sie einfachunique
-erase
nach der Sortierung.Beachten Sie, dass Sie verwenden sollten
lower_bound
,upper_bound
undequal_range
eher alsfind
oderfind_if
zu verwenden, die Vorteile der sortiert Daten.InformationsquelleAutor ikh
Ungeordnete-set verwendet eine hash-Tabelle, um in der Nähe von O(1) Zeit mit der Suche. Dies geschieht, indem ein hash des Schlüssels zur Berechnung der offset des Elements-Sie-sind-suchen (Schlüssel) aus dem Anfang des Datensatzes. Es sei denn, Ihr Datensatz ist klein (wie
char
s) unterschiedliche Schlüssel haben können dem gleichen hash (eine Kollision).Zur Minimierung von Kollisionen eine ungeordnete-set haben um die Daten zu halten-store ziemlich Dünn besiedelt. Dies bedeutet, dass die Suche nach einem Schlüssel wird ochstens O(1) Zeit (es sei denn, es ist eine Kollision).
Jedoch bei der Iteration durch eine hash-Tabelle unserer iterator wird auch eine Menge ungenutzten Raum in unserem datastore-die verlangsamt die Suche nach dem nächsten element, durch unsere iterator. Wir könnten verbinden Sie benachbarte Elemente in die hash-Tabelle mit extra Zeiger, aber ich glaube nicht, dass eine ungeordnete-set so.
Im Lichte der oben genannten, ich schlage vor, Sie verwenden einen sortierten Vektor für Ihre "set". Mit bisections Sie können nach dem speichern in O(log n) Zeit und das Durchlaufen der Liste ist trivial. Ein Vektor hat den zusätzlichen Vorteil, dass der Speicher zusammenhängend ist, so dass Sie sind weniger wahrscheinlich zu erleben-cache findet.
InformationsquelleAutor doron