Sin embargo djb2
, como se presenta en stackoverflow por cnicutar , es casi seguro que sea mejor, creo que vale la pena mostrar el K&R hashes de :
1) Aparentemente un algoritmo hash terrible , como se presenta en K&R 1st edition ( fuente )
unsigned long hash(unsigned char *str)
{
unsigned int hash = 0;
int c;
while (c = *str++)
hash += c;
return hash;
}
2) Probablemente un algoritmo hash bastante decente, como se presenta en K&R versión 2 (verificado por mí en la página 144 del libro); NB: asegúrese de eliminar % HASHSIZE
de la declaración de devolución si planea hacer el tamaño del módulo a la longitud de su matriz fuera del algoritmo hash. Además, te recomiendo que hagas el tipo return y "hashval" en unsigned long
lugar del simple unsigned
(int).
unsigned hash(char *s)
{
unsigned hashval;
for (hashval = 0; *s != '\0'; s++)
hashval = *s + 31*hashval;
return hashval % HASHSIZE;
}
Tenga en cuenta que, a partir de los dos algoritmos, está claro que una razón por la que el hash de la primera edición es tan terrible es porque NO toma en consideración el orden de los caracteres de la cadena , por hash("ab")
lo que devolvería el mismo valor que hash("ba")
. Sin embargo, esto no es así con el hash de la 2da edición, que (¡mucho mejor!) Devolvería dos valores diferentes para esas cadenas.
Las funciones de hash GCC C ++ 11 utilizadas para unordered_map
(una plantilla de tabla hash) y unordered_set
(una plantilla de conjunto hash) parecen ser las siguientes.
Código:
// 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;
}