web-dev-qa-db-fra.com

Pourquoi utilisons-nous le palpage linéaire dans les tables de hachage lorsqu'il existe un chaînage séparé lié à des listes?

J'ai récemment découvert différentes méthodes pour gérer les collisions dans les tables de hachage. Et vu que le chaînage séparé avec des listes chaînées est toujours plus efficace en temps, et pour l'efficacité de l'espace, nous allouons une mémoire prédéfinie pour le sondage linéaire que nous ne pourrions pas utiliser plus tard, pour le chaînage séparé, nous utilisons la mémoire dynamiquement, tout comme le chaînage séparé avec la liste chaînée pas plus efficace que le palpage linéaire? Si oui, pourquoi utilisons-nous alors le palpage linéaire?

27
Adilli Adil

Je suis surpris que vous ayez vu le hachage chaîné plus rapide que le palpage linéaire - en pratique, le palpage linéaire est généralement beaucoup plus rapide que le chaînage. Cela est principalement dû à localité de référence , car les accès effectués en sondage linéaire ont tendance à être plus proches en mémoire que les accès effectués en hachage chaîné.

Il y a d'autres victoires en palpage linéaire. Par exemple, les insertions dans une table de hachage de sondage linéaire ne nécessitent pas de nouvelles allocations (à moins que vous ne ressassiez la table), donc dans des applications comme les routeurs réseau où la mémoire est rare, il est bon de savoir qu'une fois la table configurée, les éléments peuvent y être placés sans risque d'échec malloc.

Une faiblesse du palpage linéaire est que, avec un mauvais choix de fonction de hachage, clustering primaire peut entraîner une dégradation significative des performances de la table. Bien que le hachage chaîné puisse encore souffrir de mauvaises fonctions de hachage, il est moins sensible aux éléments avec des codes de hachage proches, qui n'ont pas d'impact négatif sur l'exécution. Théoriquement, le sondage linéaire ne donne que des recherches O(1) recherchées si les fonctions de hachage sont indépendantes de 5 ou si il y a suffisamment d'entropie dans les clés =. Il existe de nombreuses façons de résoudre ce problème, car en utilisant la technique Hashcotch ou Hopscotch hashing , les deux ont des pires cas significativement meilleurs que le palpage linéaire Vanilla.

L'autre faiblesse du palpage linéaire est que ses performances se dégradent considérablement à mesure que le facteur de charge approche 1. Vous pouvez résoudre ce problème soit en ressassant périodiquement, soit en utilisant la technique de hachage Robin Hood décrite ci-dessus.

J'espère que cela t'aides!

41
templatetypedef

Le sondage linéaire est en fait plus efficace en mémoire lorsque la table de hachage est presque pleine.

Historiquement, on avait très, très peu de mémoire, donc chaque octet comptait (et il y a encore des cas où la mémoire est très limitée).

Pourquoi utilise-t-il moins de mémoire?

Considérez à quoi ressemblent les tableaux: (variations de chaînage séparées selon Wikipedia - il y a aussi d'autres variantes, mais elles utilisent généralement plus de mémoire)

Linear             Separate chaining #1    Separate chaining #2
probing            List head in table      Pointer in table
|------|           |------|---|            |---|    |------|---|
|Object|           |Object|Ptr|            |Ptr| -> |Object|Ptr|
|------|           |------|---|            |---|    |------|---|
|Object|           |Object|Ptr|            |Ptr| -> |Object|Ptr|
|------|           |------|---|            |---|    |------|---|
| NULL |           | NULL |Ptr|            |Ptr|
|------|           |------|---|            |---|
 .                  .                       .
 .                  .                       .
 .                  .                       .

(Ptr signifie "pointeur" - tout pointeur ne pointant pas vers quelque chose peut être considéré comme NULL)

Le chaînage séparé # 1 utilise clairement plus de mémoire que le palpage linéaire (toujours), car chaque élément du tableau est plus grand de la taille du pointeur.

Le chaînage séparé # 2 pourrait avoir un avantage lorsqu'il n'y a pas grand-chose dans la table, mais quand il sera plein, il y aura environ 2 pointeurs supplémentaires flottant pour chaque élément.


templatetypedef a probablement raison de dire que le sondage linéaire est généralement plus rapide (il a rarement tort), mais il est généralement enseigné que le chaînage séparé est plus rapide, et vous le voyez dans les principales API (comme implémentations Java =, par exemple), peut-être à cause de cela, pour éviter les cas où le sondage linéaire est beaucoup plus lent (avec quelques valeurs bien sélectionnées, vous pouvez rapidement accéder à O(n) les performances avec le sondage linéaire alors que le chaînage séparé auraient toujours été O(1)), ou peut-être pour une autre raison.

9
Dukeling