Angenommen, ich wollte Daten mit einer Zeichenfolge als Schlüssel zuordnen. Welchen Container hätte ich wählen sollen map
oder unordered_map
? unordered_map
nimmt mehr Speicherplatz in Anspruch, nehmen wir also an, dass Speicher kein Problem ist und das Problem die Geschwindigkeit ist.
unordered_map
sollte im Allgemeinen eine durchschnittliche Komplexität von O (1) mit dem schlechtesten Fall von O (n) ergeben. In welchen Fällen würde es zu O (n) kommen? Wann wird ein map
zeiteffizienter als unordered_map
? Kommt es vor, wenn n klein ist?
Angenommen, ich würde STL unordered_map
mit dem Standard-Haser Vs. Karte. Zeichenfolge ist der Schlüssel.
Sollte ich es vorziehen, wenn ich über die Elemente iteriere, anstatt jedes Mal auf ein einzelnes Element zuzugreifen map
?
quelle
unordered_map
verwendet mehr Speicher?Antworten:
In der Praxis ist der Speicher
unordered_map
immer schneller, wenn Sie auf einzelne Elemente zugreifen möchten.Der schlimmste Fall ist theoretisch und an einen einzigen Hash gebunden, der alle Elemente berücksichtigt. Dies ist nicht von praktischer Relevanz. Das
unordered_map
wird langsamer, sobald Sie mindestens N Elemente haben, die zu demselben Hash gehören. Dies ist auch nicht von praktischer Relevanz. In einigen speziellen Szenarien können Sie einen bestimmten Hashing-Algorithmus verwenden, der eine gleichmäßigere Verteilung gewährleistet. Für gewöhnliche Zeichenfolgen, die kein bestimmtes Muster aufweisen, sind die mitgelieferten generischen Hash-Funktionenunordered_map
genauso gut.Wenn Sie die Karte (mithilfe von Iteratoren) sortiert durchlaufen möchten, können Sie sie nicht verwenden
unordered_map
. Im Gegenteil,map
dies erlaubt nicht nur, sondern kann Ihnen auch das nächste Element in einer Karte liefern, das auf einer Annäherung des Schlüssels basiert (siehelower_bound
undupper_bound
Methoden).quelle
| map | unordered_map --------------------------------------------------------- element ordering | strict weak | n/a | | common implementation | balanced tree | hash table | or red-black tree| | | search time | log(n) | O(1) if there are no hash collisions | | Up to O(n) if there are hash collisions | | O(n) when hash is the same for any key | | Insertion time | log(n)+rebalance | Same as search | | Deletion time | log(n)+rebalance | Same as search | | needs comparators | only operator < | only operator == | | needs hash function | no | yes | | common use case | when good hash is| In most other cases. | not possible or | | too slow. Or when| | order is required|
quelle
log(n)
Wenn Sie eine so schlechte Hash-Funktion haben, die für alle Eingabestirngs den gleichen Hash-Wert erzeugt (dh Kollisionen erzeugt) ...
Es sind immer die Fragen der Anforderungen und der Art / Menge der Daten, die Sie haben.
Es sind nur verschiedene Strukturen. Es ist besser, eine Auswahl zu treffen, um einen von ihnen zu verwenden, abhängig von Ihren typischen Anwendungsfällen (unter Berücksichtigung der Art Ihrer Daten und ihrer Menge).
Bei kleinen Datenmengen hängt alles von einer bestimmten STL-Implementierung ab ... Manchmal kann sogar ein einfacher Vektor / Array schneller sein als assoziative Container ...
quelle
Profil und dann entscheiden.
unordered_map
ist in der Regel schneller, variiert jedoch von Fall zu Fall.Wenn das Hashing nicht gut ist und eine Reihe von Elementen denselben Bins zugewiesen werden.
Wahrscheinlich nicht, aber profilieren Sie es, wenn Sie sich wirklich interessieren. Es ist äußerst unwahrscheinlich, dass ein Container mit einer geringen Größe der Engpass Ihres Programms ist. Auf jeden
vector
Fall kann eine einfache Suche mit linearer Suche in solchen Fällen schneller sein.Das Wichtigste bei der Entscheidung sind die Anforderungen an die Bestellung und das Fehlen einer Iterator-Ungültigmachung. Wenn Sie beides brauchen, müssen Sie es so ziemlich benutzen
map
. Ansonsten ,unordered_map
.quelle