我在为哈希表实现哈希函数时遇到了麻烦。
我想哈希我的话,A = 1,B = 2,C = 3,依此类推。字母在单词中的位置是无关紧要的,因为我们会考虑单词的排列。此外,字母的情况也与此问题无关,因此a的值= A = 1的值。
对于字符串,abc = 1 + 2 + 3 = 6,bc = 2 + 3 = 5等
对于ab = 3和aaa = 3的情况,我已经有办法处理这种情况。现在我只想得到哈希值。
我现在遇到的问题是aaa给了我1,ab给了我2。
以下是我的代码:
int hash(char *word)
{
int h = 1;
int i, j;
char *A;
char *a;
// an array of 26 slots for 26 uppercase letters in the alphabet
A = (char *)malloc(26 * sizeof(char));
// an array of 26 slots for 26 lowercase letters in the alphabet
a = (char *)malloc(26 * sizeof(char));
for (i = 0; i < 26; i++) {
A[i] = (char)(i + 65); // fill the array from A to Z
a[i] = (char)(i + 97); // fill the array from a to z
}
for (i = 0; i < strlen(word); i++) {
//printf("HIT\n");
for (j = 0; j < 26; j++) {
// upper and lower case have the same hash value
if (word[i] == A[j] || word[i] == a[j]) {
h = h + j; // get the hash value of the word
//printf("HIT 2\n");
break;
}
}
}
printf("H: %d\n", h);
return h;
}
答案 0 :(得分:5)
我认为改变了
int h = 1;
到
int h = 0;
和
h = h + j;
到
h = h + j + 1;
将解决问题。
另一个问题是您忘记释放malloc
内存。此外,C中有no need to cast the result of malloc
(和家庭)。
此
for (i = 0; i < strlen(word); i++) {
将在循环的每次迭代中调用strlen
。这会降低程序的性能。使用
int len = strlen(word);
for (i = 0; i < len; i++) {
相反,由于在每次迭代中都没有调用strlen
,所以速度要快得多。最后,sizeof(char)
是1.所以你可以省略它。
答案 1 :(得分:2)
将h=h+j
更改为h = h+j+1
和h=1
到h=0
。
此外,你应该释放分配的内存,所以在返回之前包括这些行:
free(A);
free(a);
但是我不明白为什么为这么简单的任务编写如此复杂的代码。
可以编写更简单的代码:
int hash(char *word)
{
int sum=0;
while(*word != '\0')
{
if(*word >='A' && *word < 'A'+26)
sum=sum+(*word -'A' + 1);
else if(*word >='a' && *word < 'a'+26)
sum=sum+(*word -'a' + 1);
else
return -1;
word++;
}
return sum;
}
答案 2 :(得分:2)
多个问题:
为什么是动态阵列?你知道它的大小,它不会改变。你可以用
char A[26];
char a[26]; // you can also add initialisation, e.g. = {'a', 'b', ...
为什么首先是数组?
因此,here是快速解决方案,与您的代码保持密切联系。
考虑到以上所有因素,您可以简化为:
int hash(char const * string) {
int h = 0;
for (; *string; ++string) {
int index = tolower(*string) - 'a' + 1;
if ((index > 0) && (index < 27)) {
h += index;
}
}
return h;
}
当只使用非特殊字符散列单词时,您需要以某种方式处理调用者中被忽略的单词。
char hash(char const * string, int * h) {
*h = 0;
for (; *string; ++string) {
int index = tolower(*string) - 'a' + 1;
if ((index > 0) && (index < 27)) {
*h += index;
} else {
return 0;
}
}
return 1;
}
通过这种方式,您可以使用返回值来测试是否应该忽略该单词。