Maintenant que std
a une vraie carte de hachage dans unordered_map
, pourquoi (ou quand) que vous voudriez toujours utiliser le bon vieux map
sur unordered_map
sur les systèmes où il existe réellement? Y a-t-il des situations évidentes que je ne peux pas voir immédiatement?Le choix entre std :: carte et std :: unordered_map
Répondre
En tant que already mentioned, map
permet d'itérer sur les éléments de manière triée, mais pas unordered_map
. Ceci est très important dans de nombreuses situations, par exemple l'affichage d'une collection (par exemple un carnet d'adresses). Cela se manifeste également d'autres façons indirectes comme: (1) Démarrer l'itération de l'itérateur retourné par find()
, ou (2) l'existence de fonctions membres comme lower_bound()
.
Aussi, je pense qu'il ya une certaine différence dans le pire des cas recherche complexité.
Pour
map
, il est O (logn)Pour
unordered_map
, il est O (N) [Cette peut se produire lorsque la fonction de hachage n'est pas bon conduit à trop de collisions de hachage .]
La même chose est valable pour pire des cassuppression complexité.
vous avez raison sur le pire des cas, mais ce post est en quelque sorte trompeur - comme en moyenne std :: unordered_map est O (1) pour la complexité de recherche qui est beaucoup mieux que std :: map –
Il est très important de comprendre que pour certaines applications, la pire des performances est essentielle à connaître et est le facteur décisif. Pour certains systèmes durs en temps réel, il n'est pas acceptable d'avoir un pire cas linéaire comme la hashtable. std :: map est toujours O (lg N), ce qui est une très belle propriété à avoir. –
Je pense qu'il est évident que vous utiliseriez le std::map
pour parcourir les éléments de la carte dans l'ordre.
Vous pouvez également l'utiliser lorsque vous préférez écrire un opérateur de comparaison (qui est intuitif) au lieu d'une fonction de hachage (qui est généralement très peu intuitive).
En plus des réponses ci-dessus, vous devriez également noter que juste parce que unordered_map
est une vitesse constante (O(1)
) ne veut pas dire qu'il est plus rapide que map
(de l'ordre log(N)
). La constante peut être plus grande que log(N)
, d'autant plus que N
est limitée par 2 (ou 2).
Donc, en plus des autres réponses (map
maintient l'ordre et les fonctions de hachage peuvent être difficiles), il se peut que map
est plus performant.
Par exemple, dans un programme que je courais un blog post j'ai vu que pour VS10 std::unordered_map
était plus lent que std::map
(bien que boost::unordered_map
était plus rapide que les deux).
note 3 au 5 barres.
quelle est la valeur de N dans ce graphique? – paulm
@paulm, comme je l'ai déclaré dans le [blog] (http://lanzkron.wordpress.com/2010/06/02/optimizing-collatz-for-klutzes/) 'N = 10.000.000'. – Motti
Le lien de blog est allé le chemin du dodo, et les résultats présentés ici sont de peu de valeur sans ce contexte, comme le temps nécessaire pour hachage vs comparer varie énormément avec la fonction de hachage exact, le type de données, la longueur et les valeurs . Cela est particulièrement important avec la VC++ Standard Library, car les fonctions de hachage sont rapides mais sujettes aux collisions: les nombres traversés inaltérés, seuls 10 caractères espacés le long d'une chaîne de longueur quelconque sont combinés dans la valeur de hachage, les comptes de baquets ne sont pas premiers. (GNU est à l'extrémité opposée du spectre). –
Cela est dû à Chandler Carruth de Google dans son CppCon 2014 lecture
std::map
est (considéré par beaucoup comme) pas utile pour le travail axé sur la performance: Si vous voulez O (1) -amortized accès, utilisez un tableau associatif approprié (ou par défaut d'un, std::unorderded_map
); Si vous voulez un accès séquentiel trié, utilisez quelque chose basé sur un vecteur.
En outre, std::map
est un arbre équilibré; et vous devez le traverser, ou le rééquilibrer, incroyablement souvent. Ce sont respectivement les opérations cache-killer et cache-apocalypse ... alors dites NON à std::map
.
Vous pourriez être intéressé par this SO question sur les implémentations de mappage de hachage efficaces.
(PS -. std::unordered_map
est cache-hostile, car il utilise des listes chaînées comme des seaux)
Supposons que vous avez des clés très grandes, peut-être de grandes chaînes. Pour créer une valeur de hachage pour une grande chaîne, vous devez parcourir toute la chaîne du début à la fin. Il faudra au moins un temps linéaire à la longueur de la clé. Toutefois, lorsque vous recherchez uniquement un arbre binaire à l'aide de l'opérateur >
de la clé, chaque comparaison de chaîne peut renvoyer lorsque la première disparité est trouvée. C'est généralement très tôt pour les grandes chaînes. Ce raisonnement peut être appliqué à la fonction find
de std::unordered_map
et std::map
. Si la nature de la clé est telle qu'il faut plus de temps pour produire un hachage (dans le cas de std::unordered_map
) que pour trouver l'emplacement d'un élément en utilisant la recherche binaire (dans le cas de std::map
), la recherche devrait être plus rapide une clé dans le std::map
. Il est assez facile de penser à des scénarios où ce serait le cas, mais ils seraient assez rares dans la pratique, je crois.
Copie possible de [Y a-t-il un avantage à utiliser la carte sur \ _map non ordonné en cas de clés triviales?] (Http://stackoverflow.com/questions/2196995/is-there-any-advantage-of-using- map-over-unordered-map-in-case-of-trivial-keys) –