Fonction de hachage pour les chaînes de caractères en C
Je suis en train d'essayer de mettre en œuvre une fonction de hachage pour mon programme en C. j'ai trouvé beaucoup de solutions possibles, mais je ne les comprends pas. Ce qui suit est la fonction de hachage:
int hash(const char *word) {
int hash = 0;
int n;
for (int i = 0; word[i] != 'int hash(const char *word) {
int hash = 0;
int n;
for (int i = 0; word[i] != '\0'; i++) {
//alphabet case
if (isalpha(word[i]))
n = word[i] - 'a' + 1;
else //comma case
n = 27;
hash = ((hash << 3) + n) % SIZE;
}
return hash;
}
'; i++) {
//alphabet case
if (isalpha(word[i]))
n = word[i] - 'a' + 1;
else //comma case
n = 27;
hash = ((hash << 3) + n) % SIZE;
}
return hash;
}
Pourquoi sommes-nous en soustrayant 'a'+1
de word[i]
? Aussi, pourquoi faisons-nous la suite: hash = ((hash << 3) + n) % SIZE
?
"Pourquoi sommes-nous en ajoutant 'a'+1 à la chaîne?" - probablement pour
n
n'est pas 0.OriginalL'auteur KishB87 | 2013-12-09
Vous devez vous connecter pour publier un commentaire.
Pourquoi sommes-nous en ajoutant 'a'+1 à la chaîne?
si on ne rajoute pas de "+1",
hash("a") = hash("aa") = has("aaa")
... découvrez ci-dessous le code, pourquoi faisons-nous le texte suivant: "hash = ((hash << 3) + n) % TAILLE"?
OriginalL'auteur Jason Heo
Nous ne sommes pas en ajoutant des, nous sont soustraction. En outre, nous ne pouvons pas le faire à la chaîne, nous le faisons pour les caractères un à un.
Ici est ce qu'il fait, selon les auteurs, les intentions d': étant donné une lettre de
a
àz
, l'expression produit le numéro de séquence de la lettre:'a'
produit 1,'b'
produit 2,'c'
produit 3, et ainsi de suite.Malheureusement, cette mise en œuvre est cassé: lorsque la lettre est en majuscule,
isalpha
retournetrue
, mais le résultat de l'expression ne vous donne pas le numéro de lettre. En fait, si votre ordinateur utilise l'encodage qui est cohérent avec les codes ASCII, le résultat devrait être un nombre négatif.Cette multiplie l'état de la valeur de hachage par huit (maj par trois est la même que la multiplication par huit), ajoute le numéro de la lettre, puis les limites de la valeur en obtenant le reste de la division par
SIZE
.Depuis la valeur réelle de la code de hachage est de peu d'intérêt, tant il est sensible aux petits changements dans la parole, vous pouvez utiliser cette fonction à la place:
Cet algorithme (sans le
SIZE
limite) est utilisé pour le calcul des codes de hachage deString
s en Java. Il est très simple et très efficace.Vous avez raison, je ne pense pas que EBSDIC, où les majuscules ont plus de codes que de minuscules. Merci!
EBCDIC .........
i
devrait avoir le typesize_t
et il pourrait être mieux de jeterword[i]
commeunsigned char
.OriginalL'auteur dasblinkenlight
Nous ne sommes pas ...
-
moyens de soustraire, de ne pas ajouter, et le mot[i] est un caractère de la chaîne, pas la chaîne. Nous sommes donc en soustrayant 'a' et en ajoutant 1 à chaque caractère de la chaîne.Si le mot[i] est une lettre minuscule, alors
word[i] - 'a' + 1
calcule le nombre de la lettre: "a" - > 1, ... 'z' -> 26. Si ce n'était pas une lettre minuscule? Ainsi, les caractères non-alphabétiques (et pas seulement par des virgules, contrairement à l'observation) sont mappés à 27, mais les lettres majuscules, le cas échéant, entraîner un comportement indéfini.Ce qui multiplie la précédente valeur de hachage par 8, puis ajoute la valeur 1 ... 27 pour le caractère actuel, et garantit que le résultat ne dépasse pas la TAILLE, qui est sans doute le nombre de hachage seaux. Si la chaîne contient plus de caractères que la taille de mot /3, les caractères initiaux seront décalés. Si la TAILLE est une puissance de 2 et la chaîne a plus de TAILLE/3 caractères, puis tous les autres caractères seront décalés.
Comment ça marche, mais ce n'est pas une très bonne fonction de hachage. Hormis le code ayant une erreur de commentaire et de ne pas la manipulation des lettres majuscules et minuscules, il également ne pas manipuler des chaînes de bien, car les caractères vont être déplacé, comme mentionné. Aussi l'évolution et l'opération d'ajout combine des caractères adjacents dans un non-aléatoire, de sorte qu'il va produire plus de compartiment de hachage de collisions que l'optimum. Cette fonction de hachage est rapide, mais il y a mieux rapide de fonctions de hachage. Voir https://en.wikipedia.org/wiki/Hash_function pour plus d'informations.
Vous avez raison quant à la disparité entre la virgule et le code, mais vous avez tort sur il n'y a pas indéfini de cas ... des lettres majuscules, pour qui isalpha est vrai, ne sont pas répertoriées 1-26; ce qu'ils ne répertoriées est indéfini, car C n'a pas de mandat particulier de codage.
Donc, ce serait de définir une bonne fonction de hachage?
Merci pour la correction sur les lettres majuscules, insouciant de me rater. KishB87: une bonne fonction de hachage va dresser la carte de ses chaînes d'entrée de manière assez homogène pour l'ensemble de la valeur de hachage de l'espace. Définir une fonction qui va bien n'est pas simple, mais il aura au moins traiter tous les caractères possibles dans son entrée, cette fonction ne fonctionne pas.
Il est en effet potentiel d'un comportement indéfini, mais pas là où vous le décrire. Si le
char
type est signé,isalpha(word[i])
a un comportement indéfini négatifchar
valeurs. Pour éviter ce problème, l'argument deisalpha
doit être jeté commeunsigned char
:isalpha((unsigned char)word[i])
. Il n'y a plus un comportement indéfini ici:hash = ((hash << 3) + n) % SIZE
: à gauche décalage des valeurs négatives est un comportement indéfini. Vous pouvez avoir une valeur négative pourhash
si le premier caractère est une lettre majuscule. Modifier le type dehash
etc
àunsigned int
pour éviter cela.OriginalL'auteur Jim Balter
La soustraction est une tentative de convertir les lettres en minuscules pour les numéros de
1
à26
. La virgule est converti à27
mais les majuscules sont converties en valeurs négatives (pour le jeu de caractères ASCII), ce qui a des effets secondaires néfastes.En effet, il est possible comportement indéfini:
Si le
char
type est signé,isalpha(word[i])
a un comportement indéfini négatifchar
valeurs. Pour éviter ce problème, l'argument deisalpha
doit être jeté commeunsigned char
:isalpha((unsigned char)word[i])
.hash = ((hash << 3) + n) % SIZE
a le potentiel de comportement indéfini trop: à gauche décalage des valeurs négatives est un comportement indéfini. Vous pouvez avoir une valeur négative pourhash
si le premier caractère est une lettre majuscule. Modifier le type dehash
etc
àunsigned int
pour éviter cela.L'expression
hash = ((hash << 3) + n) % SIZE
est utilisé pour combiner les bits de tous les caractères en une valeur comprise entre0
etSIZE-1
. Notez cependant que siSIZE
n'est pas une valeur non signée, l'expression peut produire une valeur négative entre-SIZE+1
et-1
, qui aurait probablement des effets secondaires néfastes.Le transcodage des valeurs de caractère n'a pas vraiment d'aider à la production d'une bonne fonction de hachage.
Ici est un plus sûr de la version:
OriginalL'auteur chqrlie