Obwohl es mit ziemlicher Sicherheit besser ist djb2, wie von cnicutar auf stackoverflow vorgestellt , lohnt es sich auch, die K & R- Hashes zu zeigen:
1) Anscheinend ein schrecklicher Hash-Algorithmus, wie in K & R 1st Edition ( Quelle ) vorgestellt.
unsigned long hash(unsigned char *str)
{
unsigned int hash = 0;
int c;
while (c = *str++)
hash += c;
return hash;
}
2) Wahrscheinlich ein ziemlich anständiger Hash-Algorithmus, wie er in K & R Version 2 vorgestellt wird (von mir auf S. 144 des Buches verifiziert); NB: Stellen Sie sicher, dass Sie diese % HASHSIZEaus der return-Anweisung entfernen, wenn Sie vorhaben, den Modul außerhalb des Hash-Algorithmus auf Ihre Array-Länge zu dimensionieren. Außerdem empfehle ich Ihnen, unsigned longanstelle des einfachen unsigned(int) den Typ return und "hashval" vorzunehmen .
unsigned hash(char *s)
{
unsigned hashval;
for (hashval = 0; *s != '\0'; s++)
hashval = *s + 31*hashval;
return hashval % HASHSIZE;
}
Beachten Sie, dass aus den beiden Algorithmen hervorgeht, dass ein Grund dafür, dass der Hash der 1. Ausgabe so schrecklich ist, darin besteht , dass die Reihenfolge der Zeichenfolgen NICHT berücksichtigt wird und hash("ab")daher der gleiche Wert wie zurückgegeben wird hash("ba"). Dies ist jedoch beim Hash der 2. Ausgabe nicht der Fall, der (viel besser!) Zwei verschiedene Werte für diese Zeichenfolgen zurückgeben würde.
Die für unordered_map(eine Hash-Tabellenvorlage) und unordered_set(eine Hash-Set-Vorlage) verwendeten GCC C ++ 11-Hashing-Funktionen scheinen wie folgt zu sein.
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;
}