Ich habe eine Sammlung von std::set
. Ich möchte die Schnittmenge aller Sätze in dieser Sammlung auf die schnellste Weise finden. Die Anzahl der Sätze in der Sammlung ist normalerweise sehr klein (~ 5-10), und die Anzahl der Elemente in jedem Satz ist normalerweise kleiner als 1000, kann aber gelegentlich bis zu ungefähr 10000 gehen. Aber ich muss diese Schnittpunkte zig machen Tausende von Zeit, so schnell wie möglich. Ich habe versucht, einige Methoden wie folgt zu bewerten:
std::set
-Objekt, das zunächst den ersten Satz kopiert. Dann iteriert es für nachfolgende Mengen über alle Elemente von sich selbst und den i-ten Satz der Sammlung und entfernt bei Bedarf Elemente von sich selbst. std::set_intersection
in einem temporären std::set
, tauschen Sie den Inhalt gegen einen aktuellen Satz aus, suchen Sie dann erneut den Schnittpunkt des aktuellen Satzes mit dem nächsten Satz und fügen Sie ihn in den Temp-Satz ein usw. vector
als Zielcontainer anstelle von std::set
. std::list
anstelle von vector
, wird das Verdächtigen von list
schnellere Löschvorgänge von der Mitte aus ermöglichen. std::unordered_set
) und Prüfen auf alle Elemente in allen Mengen. Wie sich herausstellte, ist die Verwendung von vector
geringfügig schneller, wenn die Anzahl der Elemente in jedem Satz klein ist, und list
ist bei größeren Mengen geringfügig schneller. In-Place mit set
ist wesentlich langsamer als beide, gefolgt von set_intersection
und Hash-Sets. Gibt es einen schnelleren Algorithmus / Datenstruktur / Tricks, um dies zu erreichen? Ich kann Code-Snippets bei Bedarf bereitstellen. Vielen Dank!
Sie können eine Verallgemeinerung von std::set_intersection()
versuchen: Der Algorithmus verwendet Iteratoren für alle Mengen:
end()
der entsprechenden Menge erreicht hat, sind Sie fertig. Daher kann angenommen werden, dass alle Iteratoren gültig sind. x
. std::find_if()
das erste Element mindestens so groß wie x
. x
ist, machen Sie ihn zum neuen Kandidatenwert und suchen Sie erneut in der Reihenfolge der Iteratoren. x
haben, haben Sie ein Element der Schnittmenge gefunden: Zeichnen Sie es auf, inkrementieren Sie alle Iteratoren, beginnen Sie von vorne. Die Nacht ist ein guter Ratgeber und ich denke, ich habe vielleicht eine Idee;)
Deshalb ist, wo Geschwindigkeit zählt, ein vector
(oder vielleicht ein deque
) so großartige Strukturen: Sie spielen sehr gut mit dem Gedächtnis. Daher würde ich definitiv empfehlen, vector
als unsere zwischengeschalteten Strukturen zu verwenden; Es muss jedoch darauf geachtet werden, dass nur eine Extremität eingefügt / gelöscht wird, um eine Verlagerung zu vermeiden.
Also habe ich über einen ziemlich einfachen Ansatz nachgedacht:
%Vor%Es scheint korrekt zu sein, aber ich kann seine Geschwindigkeit natürlich nicht garantieren.
Tags und Links algorithm c++ stl set-intersection