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 % HASHSIZE
aus 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 long
anstelle 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;
}