Wie wähle ich zwischen map und unordered_map?

83

Angenommen, ich wollte Daten mit einer Zeichenfolge als Schlüssel zuordnen. Welchen Container hätte ich wählen sollen mapoder unordered_map? unordered_mapnimmt mehr Speicherplatz in Anspruch, nehmen wir also an, dass Speicher kein Problem ist und das Problem die Geschwindigkeit ist.

unordered_mapsollte 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 mapzeiteffizienter als unordered_map? Kommt es vor, wenn n klein ist?

Angenommen, ich würde STL unordered_mapmit 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?

StackHeapCollision
quelle
3
Müssen Elemente in der Zuordnung sortiert werden?
Einige Programmierer Typ
Welche Implementierung von unordered_mapverwendet mehr Speicher?
Peter Wood
Sie haben immer Speicher-Overhead in einer Hash-Map, obwohl dies normalerweise vernachlässigbar ist.
Ypnos
Es ist ein kleiner Punkt, aber wie Sie die Iteration erwähnen, sollten Sie darauf hinweisen, dass Sie beim Iterieren beim Einfügen von Elementen die Karte der ungeordneten Karte vorziehen sollten.
John McFarlane

Antworten:

67

In der Praxis ist der Speicher unordered_mapimmer 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_mapwird 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-Funktionen unordered_mapgenauso gut.

Wenn Sie die Karte (mithilfe von Iteratoren) sortiert durchlaufen möchten, können Sie sie nicht verwenden unordered_map. Im Gegenteil, mapdies erlaubt nicht nur, sondern kann Ihnen auch das nächste Element in einer Karte liefern, das auf einer Annäherung des Schlüssels basiert (siehe lower_boundund upper_boundMethoden).

ypnos
quelle
6
Diese Antwort ist bestenfalls irreführend. Es ist nicht wahr, dass "unordered_map für den Zugriff auf einzelne Elemente immer schneller ist" - das einzige, was ich mir vorstellen kann, ist, dass es immer schneller amortisiert und asymptotisch ist . Das "amortisierte" ist in der Praxis eine wichtige Einschränkung: Wenn ich mich richtig an meine Hash-Tabellen erinnere, wenn Sie sie durch Einfügen von Elementen vergrößern, wird es mit einer Ω (n) -Operation "hiccup" immer wieder. Das kann eine bestimmte App tolerieren oder auch nicht.
Don Hatch
209
                       | 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
6
Kommentar zur allgemeinen Implementierung: Ein Rot-Schwarz-Baum ist eine Art ausgeglichener Baum (oder genauer gesagt eine Art selbstausgleichender binärer Suchbaum).
HelloGoodbye
2
Neuausrichtung würde nicht mehr alslog(n)
mtk
Was ist mit dem Durchlaufen aller Elemente?
Shashwat
7

In welchen Fällen würde es zu O (n) kommen?

Wenn Sie eine so schlechte Hash-Funktion haben, die für alle Eingabestirngs den gleichen Hash-Wert erzeugt (dh Kollisionen erzeugt) ...

Welchen Container hätte ich wählen sollen, map oder unordered_map?

Es sind immer die Fragen der Anforderungen und der Art / Menge der Daten, die Sie haben.

Wann wird eine Karte zeiteffizienter als unordered_map?

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).

Hppaen es, wenn n klein ist?

Bei kleinen Datenmengen hängt alles von einer bestimmten STL-Implementierung ab ... Manchmal kann sogar ein einfacher Vektor / Array schneller sein als assoziative Container ...

zaufi
quelle
7

Welchen Container hätte ich wählen sollen, map oder unordered_map? unordered_map beansprucht mehr Speicher. Nehmen wir also an, Speicher ist kein Problem, und das Problem ist die Geschwindigkeit.

Profil und dann entscheiden. unordered_mapist in der Regel schneller, variiert jedoch von Fall zu Fall.

In welchen Fällen würde es zu O (n) kommen?

Wenn das Hashing nicht gut ist und eine Reihe von Elementen denselben Bins zugewiesen werden.

Wann wird eine Karte zeiteffizienter als unordered_map? Passiert es, wenn n klein ist?

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 vectorFall 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.

Pubby
quelle