Comment puis-je Hasher une chaîne sur un int en utilisant c++?

je dois écrire ma propre fonction de hachage. Si je voulais juste faire la fonction de hachage simple qui mappe chaque lettre dans la chaîne à une valeur numérique (i.e. a=1, b=2, c=3, ...), est-il une manière que je peux effectuer cette hachage sur une chaîne sans avoir à le convertir en un c-string pour regarder chaque char? Est-il un moyen plus efficace de hachage cordes?

16
demandé sur zebraman 2010-03-29 05:04:49

9 réponses

Re la première question, bien sûr, E. g, something like:

int hash = 0;
int offset = 'a' - 1;
for(string::const_iterator it=s.begin(); it!=s.end(); ++it) {
  hash = hash << 1 | (*it - offset);
}

en ce qui concerne le second, il y a beaucoup de meilleures façons de hacher les chaînes. E. g., voir ici pour un peu de C exemples (facilement traduisibles en C++ le long des lignes de l'extrait ci-dessus).

7
répondu Alex Martelli 2012-11-05 08:38:23

D'après mon expérience personnelle, je sais que cela fonctionne et produit de bonnes distributions. (Plagié de http://www.cse.yorku.ca/~oz/hash.html):

djb2

cet algorithme (k=33) a été rapporté pour la première fois par dan bernstein il y a de nombreuses années dans comp.lang.C. une autre version de cet algorithme (maintenant favorisée par bernstein) utilise xor: hash(i) = hash (i - 1) * 33 ^ str[i]; la magie du nombre 33 (pourquoi il fonctionne mieux que beaucoup d'autres constantes, prime ou pas) n'a jamais été expliquée de manière adéquate.

unsigned long hash(unsigned char *str) {
    unsigned long hash = 5381;
    int c;

    while (c = *str++) {
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    }

    return hash;
}
8
répondu Tim Cooper 2013-09-02 14:34:06

Vous pouvez examiner chaque char individuel à partir d'une chaîne std::en utilisant le [] opérateur. Cependant, vous pouvez regarder Boost::Fonctionnel/Hachage pour obtenir des conseils sur un meilleur système de hachage. Il existe également une liste de fonctions de hachage dans c situé ici.

5
répondu wheaties 2010-03-29 01:09:14
int hash(const char *str)
{
    int h = 0;
    while (*str)
       h = h << 1 ^ *str++;
    return h;
}

si vous l'utilisez pour une table de hachage (ce que Stroustrup fait) alors vous pouvez retourner l'abs du hachage modulo un nombre premier. Ainsi, au lieu

    return (h > 0 ? h : -h) % N_BUCKETS;

pour la dernière ligne.

5
répondu Wren 2012-08-05 19:38:45

C++11 est livré avec un standard de la fonction de hachage pour les chaînes.

https://en.cppreference.com/w/cpp/string/basic_string/hash

#include <string>
#include<functional> // hash
int main(){
    std::string s = "Hello";
    std::size_t hash = std::hash<std::string>{}(s);
}
1
répondu alfC 2018-07-08 22:04:42

xor les personnages, quatre à la fois.

0
répondu Stephen 2010-03-29 01:10:12
#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

// a variation on dan bernstein's algorithm
// [http://www.cse.yorku.ca/~oz/hash.html]
template<typename Int>
struct hash {
    hash() : acc(5381) { }
    template<typename Ch>
    void operator()(Ch ch) { acc = ((acc << 5) + acc) ^ ch; }
    operator Int() const { return acc; }
    Int acc;
};

int main(int argc, char* argv[])
{
    string s("Hellp, world");
    cout << hex << showbase
        << for_each(s.begin(), s.end(), hash<unsigned long long>()) << '\n';
    return 0;
}
0
répondu wilhelmtell 2010-04-14 08:30:20

une Autre façon pour les petites chaînes de caractères:

int hash(const char* str) {
    int hash = 0;
    int c = 0;

    while (c < std::strlen(str)) {
        hash += (int)str[c] << (int)str[c+1];
        c++;
    }
    return hash;
}
0
répondu LUCAS 2015-12-07 08:04:55

Vous pouvez utiliser les fonctions de membre operator [] ou de la classe string ou des itérateurs pour accéder au char individuel d'un objet string sans le convertir en un tableau de char de style c.

pour Hasher un objet string sur un entier, vous devrez accéder à chaque char individuel de l'objet string que vous pouvez faire comme:

for (i=0; i < str.length(); i++) {
    // use str[i] or str.at(i) to access ith element.
}
-2
répondu codaddict 2010-03-29 01:10:08