web-dev-qa-db-fra.com

Pourquoi l'accès à un élément d'un dictionnaire par une clé O(1) alors que la fonction de hachage n'est peut-être pas O (1)?

Je vois comment vous pouvez accéder à votre collection par clé. Cependant, la fonction de hachage elle-même comporte de nombreuses opérations en coulisse, n'est-ce pas?

En supposant que votre fonction de hachage de Nice soit très efficace, elle peut nécessiter de nombreuses opérations.

Cela peut-il être expliqué?

70
monogate

le HashFunc lui-même a beaucoup d'opérations en coulisses

C'est certainement vrai. Cependant, le nombre de ces opérations dépend de la taille de la clé, et non de la taille de la table de hachage dans laquelle la clé est insérée: le nombre d'opérations à calculer La fonction de hachage est la même pour une clé dans une table avec dix ou dix mille entrées.

C'est pourquoi l'appel de la fonction de hachage est souvent considéré comme O (1). Cela fonctionne très bien pour les clés de taille fixe (valeurs intégrales et chaînes de longueur fixe). Il fournit également une approximation décente des clés de taille variable avec une limite supérieure pratique.

Cependant, le temps d'accès d'une table de hachage est généralement égal à O (k), où k représente la limite supérieure de la taille de la clé de hachage.

113
dasblinkenlight

O(1) ne signifie pas instantané. O(1) signifie constante sans tenir compte de la taille des données. La fonction de hachage prend un certain temps, mais ce temps ne correspond pas à la taille de la collection.

131
Paarth

Cela signifie que quelle que soit la taille de votre collection, il faudra toujours presque le même temps pour récupérer l'un de ses membres.

Donc, en d’autres termes, un dictionnaire avec 5 membres dira qu’il faut environ 0,002 ms pour accéder à l’un d’eux, ainsi que le dictionnaire de 25 membres devrait prendre quelque chose de similaire. Big O signifie complexité algorithmique par rapport à la taille de la collection au lieu d'instructions ou de fonctions exécutées

15

Si un dictionnaire/une carte est implémenté en tant que HashMap, il a un complexité du meilleur des cas de O(1), puisque dans le meilleur des cas il nécessite exactement le calcul du hachage -code de l'élément clé à récupérer, s'il n'y a pas de collision de clé.

Un hash-map peut avoir un complexité d'exécution la plus défavorable de O(n) si vous avez beaucoup de collisions clés ou une très mauvaise fonction de hachage, car dans ce cas, il se dégrade en un balayage linéaire de l'ensemble du tableau contenant les données.

En outre, O(1) ne signifie pas instantanément, cela signifie qu'il a une quantité constante. Ainsi, le choix de la bonne implémentation pour un dictionnaire peut également dépendre du nombre d'éléments de la collection, car un coût constant très élevé pour la fonction sera bien pire s'il n'y a que quelques entrées.

C'est pourquoi les dictionnaires/cartes sont mis en œuvre différemment selon les scénarios. Pour Java il existe plusieurs implémentations différentes, C++ utilise des arbres rouges/noirs, etc. Vous les avez choisis en fonction du nombre de données et de leur efficacité d'exécution optimale/moyenne/défavorable .

12
Martin C.

Théoriquement, il reste toujours O (n), car dans le pire des cas, toutes vos données peuvent avoir un hachage identique et être regroupées, auquel cas vous devez les parcourir de manière linéaire.

6
twihoX

S'il vous plaît voir post Que signifie "O (1) temps d'accès" signifie?

Le nombre d'opérations dans une fonction de hachage est sans importance tant qu'il faut la même durée (constante) pour TOUS les éléments de la collection. Par exemple, accéder à un élément d'une collection de 2 éléments prend 0,001 ms, mais l'accès à un élément d'une collection de 2 000 000 000 d'éléments nécessite 0,001 ms. Bien que la fonction de hachage puisse contenir des centaines d'instructions if et plusieurs calculs.

3
Ezra

des docs:

La récupération d'une valeur à l'aide de sa clé est très rapide, proche de O (1), car la classe T: System.Collections.Generic.Dictionary`2 est implémentée sous la forme d'une table de hachage.

Cela peut donc être O(1) mais pourrait être plus lent. Ici, vous pouvez trouver un autre sujet concernant les performances de la table de hachage: Table de hachage - pourquoi est-il plus rapide que les tableaux?

1
JeReT

Une fois que vous avez pris en compte le fait que les dictionnaires de plus en plus grands utilisent plus de mémoire, descendent plus loin dans la hiérarchie du cache et éventuellement pour ralentir l'espace de permutation sur disque, il est difficile d'affirmer qu'il s'agit bien de O (1). Les performances du dictionnaire ralentiront à mesure qu’il deviendra plus grand, ce qui donnera probablement une complexité temporelle à O (log N). Ne me crois pas? Essayez vous-même avec 1, 100, 1000, 10000, etc. éléments du dictionnaire, jusqu’à 100 milliards, et mesurez le temps qu’il faut en pratique pour rechercher un élément.

Cependant, si vous faites l'hypothèse simplificatrice que toute la mémoire de votre système est une mémoire à accès aléatoire et que vous pouvez y accéder en un temps constant, vous pouvez alors prétendre que le dictionnaire est O (1). Cette hypothèse est courante, même si elle n’est pas vraiment vraie pour toutes les machines disposant d’un espace de permutation de disque, et reste assez discutable dans tous les cas compte tenu des différents niveaux de cache du processeur.

1
Ed Avis