Bien que djb2
, comme présenté sur stackoverflow par cnicutar , c'est presque certainement mieux, je pense que cela vaut la peine de montrer le K&R hachages aussi:
1) Apparemment un algorithme de hachage terrible , tel que présenté dans la 1ère édition de K&R ( source )
unsigned long hash(unsigned char *str)
{
unsigned int hash = 0;
int c;
while (c = *str++)
hash += c;
return hash;
}
2) Probablement un algorithme de hachage assez décent, tel que présenté dans K&R version 2 (vérifié par moi à la page 144 du livre); NB: assurez-vous de supprimer % HASHSIZE
de l'instruction return si vous prévoyez de faire le dimensionnement du module à la longueur de votre tableau en dehors de l'algorithme de hachage. Aussi, je vous recommande de faire le retour et le type "hashval" unsigned long
au lieu du simple unsigned
(int).
unsigned hash(char *s)
{
unsigned hashval;
for (hashval = 0; *s != '\0'; s++)
hashval = *s + 31*hashval;
return hashval % HASHSIZE;
}
Notez qu'il est clair d'après les deux algorithmes que l'une des raisons pour lesquelles le hachage de la 1ère édition est si terrible est qu'il ne prend PAS en compte l' ordre des caractères de la chaîne et hash("ab")
qu'il renvoie donc la même valeur que hash("ba")
. Ce n'est cependant pas le cas avec le hachage de la 2e édition, qui renverrait (beaucoup mieux!) Deux valeurs différentes pour ces chaînes.
Les fonctions de hachage GCC C ++ 11 utilisées pour unordered_map
(un modèle de table de hachage) et unordered_set
(un modèle de jeu de hachage) semblent être les suivantes.
Code:
// Implementation of Murmur hash for 32-bit size_t.
size_t _Hash_bytes(const void* ptr, size_t len, size_t seed)
{
const size_t m = 0x5bd1e995;
size_t hash = seed ^ len;
const char* buf = static_cast<const char*>(ptr);
// Mix 4 bytes at a time into the hash.
while (len >= 4)
{
size_t k = unaligned_load(buf);
k *= m;
k ^= k >> 24;
k *= m;
hash *= m;
hash ^= k;
buf += 4;
len -= 4;
}
// Handle the last few bytes of the input array.
switch (len)
{
case 3:
hash ^= static_cast<unsigned char>(buf[2]) << 16;
[[gnu::fallthrough]];
case 2:
hash ^= static_cast<unsigned char>(buf[1]) << 8;
[[gnu::fallthrough]];
case 1:
hash ^= static_cast<unsigned char>(buf[0]);
hash *= m;
};
// Do a few final mixes of the hash.
hash ^= hash >> 13;
hash *= m;
hash ^= hash >> 15;
return hash;
}