La seconde contrainte, c'est qu'il doit être rapide (je cherche en fait le meilleur compromis efficacité/rapidité).
Contexte : il faut produire une table de hachage de dimension assez faible (pas plus de 1024 éléments, 512 étant mieux).
On travaille sur des mots anglais.
Exemple : pour 10240 chaînes hachées sur 8 bits, j'aimerais que l'on trouve théoriquement :
- 40 fois la valeur 0b00000000
- 40 fois la valeur 0b00000001
- 40 fois la valeur 0b00000010
...
- 40 fois la valeur 0b11111111
MAJ du 12 octobre :
Après divers test, que vous pourrez lire au fil des pages de ce sujet de discussion, il s'avère que la fonction la plus intéressante* dans le contexte de ce fil de discussion, est fast_and_perfect_hash (elle est présentée au post ./170). Son nom est un peu prétentieux mais j'en prends la responsabilité

Elle est basée sur le fameux algorithme de Daniel Julius Bernstein (DJB). Pollux a considérablement optimisé en vitesse l'implémentation de base, et d'autres optimisations ont été apportées par Pen^2 et moi.
Attention, cette fonction optimisée ne fonctionne que si HASH_TABLE_SIZE est une puissance de 2 et qu'elle est inférieure ou égale à 1024. Sinon, utilisez DJBHash, la fonction originale de Daniel Julius Bernstein, qui est plus lente mais sans limites sur le modulo.
Pour les autres fonctions, vous pourrez prendre connaissance de leur efficacité dans les pages suivantes. Je n'en parle pas dans cette conclusion car, dans le contexte de ce fil de discussion, la plupart donne des résultats à peine meilleurs que la gagnante du test alors qu'elles sont beaucoup plus lentes.
Vous trouverez la source de toutes ces fonctions dans l'archive hashtest.zip, qui contient aussi et surtout la moulinette qui a permis le classement d'efficacité des fonctions.
Pour toutes les fonctions de hachage, il est mieux de les utiliser avec des modulos de nombres premiers (c'est à dire que HASH_TABLE_SIZE doit être premier). Il y a cependant 2 fonctions qui donnent de très bons résultats quand le modulo est particulier :
- Quand HASH_TABLE_SIZE vaut 256, 512 ou 1024 : fast_and_perfect_hash est la meilleure de toutes, comme cela est expliqué plus haut.
- Quand HASH_TABLE_SIZE vaut 256 : hash_toutcon. hash_toutcon produit une table aussi uniforme que DJBHash (1 point d'écart sur une variance d'à peu près 26) mais elle est plus rapide que DJBHash. Déroulée, elle serait donc forcément plus rapide que la gagnante du test (fast_and_perfect_hash).
Au début du paragraphe j'ai écrit qu'il était préférable de travailler avec des modulos de nombres premiers, et juste après je déclare que fast_and_perfect_hash et hash_toutcon sont les meilleures alors qu'elles utilisent des nombres pairs (et plus précisément : puissances de 2)... Quel est l'intérêt d'avoir une table de hachage dont la taille est une puissance de 2 ?
Cela accélère énormément le calcul final, celui que vous trouverez à la fin de chaque fonction. Le calcul d'un modulo est parmi les instructions les plus lentes à réaliser pour un microprocesseur. Quand le dénominateur d'un modulo est une puissance de 2, le calcul est sensiblement accéléré (on passe de 70 cycles processeur à 4 ou 6 cycles). Certes, la table est légèrement moins homogène, donc la recherche linéaire est un peu plus longue en moyenne (en pratique la différence d'homogénéité est très très faible, cf le comparatif du post ./216). Mais le temps gagné lors du calcul compense le temps perdu dans la recherche linéaire.
Cela est particulièrement vrai quand le nombre de collisions est raisonnable, par exemple quand 10.000 chaînes ou moins sont réparties sur une table de taille 1024. D'une manière générale, il semblerait que plus la table de hachage est grande, plus on a intérêt à lui donner une taille puissance de 2. En effet, le nombre moyen de collisions diminuant, la recherche linéaire est plus rapide et le léger défaut d'homogénéité est moins sensible, donc le temps gagné dans le calcul du modulo est plus flagrant.
* "la plus intéressante" = "donnant le meilleur compromis entre l'homogénéité de la table et la vitesse de calcul"
En l'occurrence, fast_and_perfect_hash produit la table de hachage la plus uniforme tout en étant la plus rapide.
Vous pouvez télécharger la moulinette de comparaison ici :
