C++ std::map und std::set - effizient einfügen Duplikate
Habe ich einen Haufen Daten, die voller Duplikate, und ich will zur Beseitigung der Duplikate. Sie wissen, z.B. [1, 1, 3, 5, 5, 5, 7] wird [1, 3, 5, 7].
Es sieht aus wie ich kann entweder std::map und std::set, um diese zu bewältigen. Aber ich bin mir nicht sicher ob es schneller ist, (a) legen Sie einfach alle Werte in die container, oder (b) überprüfen Sie, ob Sie bereits im container und nur einfügen, wenn Sie nicht - sind die Einsätze sehr leistungsfähig? Auch wenn es einen besseren Weg,... können Sie vorschlagen, eine schnelle Möglichkeit, dies zu tun?
Andere Frage - wenn die Daten, die ich bin, zu speichern, in Ihnen ist nicht so trivial, wie ganze zahlen, und stattdessen ist eine benutzerdefinierte Klasse, wie funktioniert der std::map zu verwalten, um Sie zu lagern (hash?) die Daten für den schnellen Zugriff per operator[]?
set
wäre mehr geeignet, da Sie nicht benötigen Sie einen zugehörigen Wert mit jedem element. Ich werde zu erraten, dass die Prüfung und dann das einfügen in den Satz langsamer sein wird als nur das einsetzen, denn Sie würden im wesentlichen werden dabei zwei Schlüssel suchen in der ehemaligen.Durch die definition einer von den beiden wird überprüfen, für dich bei ausführen einfügen. I. e. Sie wird tun, was Sie sonst mit einigen anderen container: überprüfen Sie für existance. Persönlich, ich ' D gehen mit dem set, es sei denn, Sie sind absichtlich mapping etwas, um etwas anderes.
Ist die Daten immer sortiert? Weil es aussieht wie Sie wollen, std::unique, nicht einen neuen container
Nein, es ist nicht sortiert. Aber ich brauche einen container, um die Ergebnisse aus dem original-Datensatz (die muss ich behalten).
Danke an alle für Eure Antworten. Leider kann ich nicht markieren Sie alle. 🙂
InformationsquelleAutor Gigi | 2012-10-10
Du musst angemeldet sein, um einen Kommentar abzugeben.
std::map
nicht hashing.std::unordered_map
tut, aber das ist C++11.std::map
undstd::set
beide nutzen einen Komparator, den Sie bieten. Die Klassen-templates Standardwerte für diesen Komparator, der kocht nach unten auf eineoperator<
Vergleich, aber Sie können Ihren eigenen stellen.Wenn Sie nicht brauchen, sowohl ein Schlüssel und ein Wert gespeichert werden (sieht man nicht), sollten Sie nur verwenden eine
std::set
, wie das ist, mehr angemessen ist.Des Standard nicht sagen, welche Daten die Strukturen
map
s undset
s verwenden, unter der Haube, nur dass bestimmter Aktionen für bestimmte Zeit Komplexität. In Wirklichkeit, die meisten Implementierungen, die ich bin mir dessen bewusst, verwenden ein Baum.Macht es keinen Unterschied, Zeit-Komplexität-Weise, wenn Sie
operator[]
oderinsert
, aber ich würdeinsert
oderoperator[]
vor, ich habe einensearch
gefolgt von eineminsert
wenn das Element nicht gefunden wird. Die später bedeuten würde, zwei getrennte Suchvorgänge einfügen ein Element in dem Satz.InformationsquelleAutor John Dibling
Einer
insert()
auf einen der dazugehörigen Container hat einefind()
um zu sehen, ob das Objekt vorhanden ist und fügt dann das Objekt. Einfach einfügen der Elemente in einestd::set<T>
sollte die Beseitigung der Duplikate einigermaßen effizient.Je nach Größe des Fernsehers und das Verhältnis von Duplikaten, um eindeutige Werte, kann es schneller sein, um die Objekte in
std::vector<T>
,std::sort()
dann, und verwenden Sie dannstd::unique()
zusammen mitstd::vector<T>::erase()
zu bekommen, entfernen Sie die Duplikate.insert()
[...] ist einfind()
[aber wenn nicht gefunden] fügt..." - die code-Formatierung vonfind()
es ergriffen werden könnten, von einigen Lesern als Aufruf an diefind()
API-Aufruf, in der Erwägung, dassinsert(x)
Implementierungen nicht buchstäblich.find(x)
als wenn Sie nicht vorhanden gibt es keine Aufzeichnung (iterator), in dem die Suche abgebrochen wurde, die erforderlich ist, zu überspringen, ein weiteres O(logN) Baum traveral für die tatsächliche Einbringung. Sie bekommen konnte in der Nähe mitlower_bound
gefolgt von derinsert
überlast mit einem iteratorhint
, aberinsert
Implementierungen behandelt diese intern für eine optimale Leistung.InformationsquelleAutor Dietmar Kühl
Wie oft sollten Sie es tun?
Inserts üblich ist:
Wenn Sie füllen einmal:
InformationsquelleAutor Naszta
Vorausgesetzt, der common implementation strategy for
std::map
undstd::set
, d.h. symmetrische binäre suchbäume, die beide einfügen " und "lookup", um eine Baum-traversal-um den Punkt zu finden, wo der Schlüssel sein sollte. So versagt lookup gefolgt von insertion wäre etwa doppelt so langsam wie nur einfügen.Durch eine Vergleich-Funktion, die Sie angeben (oder
std::less
, die funktioniert, wenn Sie überlastungoperator<
auf Ihrem benutzerdefinierten Typ). In jedem Fallstd::map
undstd::set
sind nicht hash-Tabellen.InformationsquelleAutor Fred Foo
std::set
undstd::map
sind sowohl umgesetzt als rot-schwarz-Baum, soweit ich weiß. Und wahrscheinlich verwenden Sie nur einsetzen würde schneller sein (dann beide, weil Sie wäre eine Verdoppelung der lookup-Zeit).Auch
map
undset
verwendenoperator <
. So lange, wie Sie Ihre Klasse definiert hatoperator <
Es würde in der Lage sein, um Sie als Schlüssel.InformationsquelleAutor tozka