Avoir une bonne fonction de hachage pour un C++ table de hachage?
Je suis dans le besoin d'un axé sur la performance fonction de hachage mise en œuvre en C++ pour une table de hachage qui je vais être de codage. Je regardai autour de moi déjà et ne se trouve que des questions demandant ce qui est une bonne fonction de hachage "en général". J'ai considéré CRC32 (mais où trouver de la bonne mise en œuvre?) et quelques algorithmes de cryptographie. Ma table, bien que, a des exigences très spécifiques.
Voici ce que le tableau sera comme:
100,000 items max
200,000 capacity (so the load is 0.5)
hashing a 6-character string which is a part of English sentence
examples: "become" "and he" ", not "
La priorité numéro un de ma table de hachage est quick search (recherche). Insertion rapide n'est pas important, mais ça va venir avec la recherche rapide. La suppression n'est pas important, et re-hachage n'est pas quelque chose que je vais être à la recherche. Pour gérer les collisions, je serai probablement à l'aide de séparé de chaînage comme décrit ici. J'ai déjà regardé cet article, mais voudrais un avis de ceux qui ont à traiter ce genre de tâche.
- J'ai également ajouté une fonction de hachage, vous aimeriez peut-être comme une autre réponse
- Si vous êtes désespéré, pourquoi n'avez-vous pas mis un rep prime sur ce?
- rep bounty: je l'avais mis si personne ne l'a voulu offrir des suggestions utiles, mais je suis agréablement surpris 🙂
- De toute façon un problème avec des primes est que vous ne pouvez pas placer des primes jusqu'à 2 jours ont passé
- Avez-vous envisagé d'utiliser un ou plusieurs des éléments suivants à des fins générales les fonctions de hachage: partow.net/programming/hashfunctions/index.html ils sont extrêmement rapide et efficace.
- Êtes-vous sûr que le rendement de la fonction de hachage est critique? Fonctions populaires sont pour faire pivoter une
unsigned int
par, disons de 3 bits et les ajouter dans le prochain octet, puis de réduire modulo un nombre premier, que l'on travaille OK pour le texte. À l'entrée d'une certaine manière, en vertu de l' (partielle) de contrôle de potentiellement malveillants parties (ils pourraient vous donner de 100 000 chaînes de hachage à quelques seaux...)? Ensuite, vous devez le rendre dur à cuire des données pour une telle attaque, peut-être par "salage" (démarrer avec un secret valeur aléatoire pour chaque table) et certains de hachage cryptographique jeté (mais pour de courtes chaînes de caractères qui pourraient ne pas être très efficace).
Vous devez vous connecter pour publier un commentaire.
Maintenant assumming vous voulez une table de hachage, et que vous voulez quelque chose de ultra-rapide qui fonctionne dans votre cas, parce que vos cordes sont à seulement 6 caractères, vous pouvez utiliser cette magic:
CRC est pour slowpokes 😉
Explication:
Cela fonctionne en jetant le contenu du pointeur de la chaîne pour "ressembler à" un size_t (int32 ou int64 basé sur la meilleure correspondance pour votre matériel). Si le contenu de la chaîne est interprétée comme un nombre brut, pas de soucis sur les personnages, et de plus, vous ensuite de décalage de bit-ce la précision nécessaire (vous ajuster ce nombre pour la meilleure performance, j'ai trouvé 2 qui fonctionne bien pour le hachage des chaînes de caractères dans un ensemble de quelques milliers).
Également la partie vraiment bien est tout bon compilateur sur le matériel moderne sera hash d'une chaîne comme celle-ci dans 1 instructions de montage, difficile de faire mieux que ça 😉
std::uint32_t
etstd::uint16_t
vous pourriez accéder en toute sécurité à tous les 6 octets de données (de la mise en œuvre, sisize_t
est de 32 bits, les deux derniers caractères ne sont pas hachés, si 64 puis, il y a une mémoire tampon de lecture de dépassement de ce qui pourrait se bloquer), puis probablement XOR compte tenu de la vitesse de la priorité. Comme le hachage est faible, à l'aide d'un premier nombre de compartiments serait de l'aide ici.Cette simple polynôme fonctionne étonnamment bien. Je le suis de Paul Larson, de Microsoft Research, qui a étudié un large éventail de fonctions de hachage hachage et de multiplicateurs.
salt
doit être initialisée à certains au hasard choisi de la valeur avant de la table de hachage est créé pour se défendre contre table de hachage attaques. Si ce n'est pas un problème pour vous, il suffit d'utiliser 0.La taille de la table est important, afin de minimiser les collisions. Des sons comme la vôtre est très bien.
(unsigned)
dans la boucle.h
est beaucoup plus grande que la taille de la table de hachage. Par exemple, avec la fonction de hachage et une chaîne de quatre caractères, h > 1E8 (100^4). Indépendamment de la redéfinition de la stratégie habituelle consiste à calculerh % bucket_count
pour calculer le seau d'index.Coup de pouce.Fonctionnel/Hash pourraient vous être utiles. Je n'ai pas essayé, donc je ne peux pas se porter garant de ses performances.
Boost a aussi un CRC bibliothèque.
Je regarde un Coup de pouce.Non ordonnée en premier (boost::unordered_map<>). Il utilise le hachage des cartes à la place des arbres binaires pour les conteneurs.
Je crois que certains STL implémentations ont classes hash_map<> container dans le stdext espace de noms.
La taille de votre table va dicter la taille de hachage à utiliser. Vous souhaitez minimiser les collisions de cours. Je ne suis pas sûr de ce que vous êtes en précisant par max des éléments et de la capacité (on dirait la même chose pour moi) En tout cas, ces chiffres donnent à penser qu'une version 32 bits de hachage serait suffisant. Vous pourriez sortir avec CRC16 (~de 65 000 possibilités), mais vous aurait probablement beaucoup de collisions à traiter. D'autre part, une collision peut être plus rapide à traiter que d'un hachage CRC32.
Je dirais, aller avec CRC32. Vous trouverez pas de pénurie de la documentation et des exemples de code. Puisque vous avez votre maximums compris et que la vitesse est une priorité, aller avec un tableau de pointeurs. Utiliser le hachage pour générer un index. Au moment de la collision, l'accroissement de l'indice jusqu'à ce que vous frappez un seau vide.. simple et rapide.
Puisque vous stockez les mots en anglais, la plupart de vos personnages seront des lettres et il n'y aura pas beaucoup de variation dans la plus importante des deux bits de vos données. De plus, j'aimerais garder très simple, il suffit à l'aide de XOR. Après tout, vous n'êtes pas à la recherche de la robustesse cryptographique, mais juste pour un raisonnablement même de la distribution. Quelque chose le long de ces lignes:
En plus de cela, avez-vous regardé std::tr1::hachage une fonction de hachage et/ou std::tr1::unordered_map comme une mise en place d'une table de hachage? L'utilisation de ces sera probablement sauver beaucoup de travail opposition à la mise en œuvre de vos propres classes.
Bien, alors vous êtes à l'aide de la droite structure de données, comme la recherche dans une table de hachage est O(1)! 🙂
Le CRC32 devrait le faire bien. La mise en œuvre n'est pas complexe, c'est principalement basée sur des XORs. Assurez-vous qu'il utilise une bonne polynôme.
Comment parler de quelque chose de simple:
Cela suppose 32 bits entiers. Il utilise 5 bits par caractère, de sorte que la valeur de hachage a seulement 30 bits en elle. Vous pouvez résoudre ce problème, peut-être, par la génération de six bits pour la première fois une ou deux caractères. Si vous jeu de caractères est assez petit, vous pourriez ne pas avoir besoin de plus de 30 bits.
Si vous avez besoin de rechercher des chaînes courtes et d'insertion n'est pas un problème, vous pourriez peut-être utiliser un B-arbre, ou un 2-3 arbre, vous n'avez pas gain de hachage dans votre cas.
De la façon dont vous le faire est de placer une lettre dans chaque nœud de sorte que vous vérifiez d'abord pour le nœud "a", puis vous cochez la case "a"'s d'enfants pour "p", et c'est pour les enfants "p", puis "l" et "e". Dans les situations où vous avez "apple" et "appliquer" vous avez besoin de chercher pour le dernier nœud (puisque la seule différence est dans le dernier "e" et "y")
Mais, mais, dans la plupart des cas, vous serez en mesure d'obtenir la parole après seulement quelques étapes ("xylophone" => "x"->"ylophone"), de sorte que vous pouvez optimiser comme ça. Cela peut être plus rapide que le hachage
Depuis C++11, C++ a fourni un
std::hash< string >( string )
. C'est probablement une bonne fonction de hachage qui fournit un une bonne répartition de hash-codes pour la plupart des chaînes de caractères.En outre, si vous envisagez de mettre en œuvre une table de hachage, vous devriez maintenant être vu à l'aide d'un C++
std::unordered_map
à la place.