我正在实现哈希函数以检查字谜,但我没有获得所需的输出。你能说出出了什么问题吗?
输出:
key[148]:val[joy]
key[174]:val[jam]
key[294]:val[paula]
key[13]:val[ulrich]
key[174]:val[cat]
key[174]:val[act]
key[148]:val[yoj]
key[265]:val[vij]
key[265]:val[jiv]
此处键值174
适用于字符串act
和cat
(字谜),但jam
不能达到相同的效果。
以下是代码段。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned long hash(char *str, size_t size) {
unsigned long hash_val = 5381;
unsigned long sum = 0;
char *val;
int i, j;
for (j = 0; j < 9; j++) {
val = malloc(strlen(str) + 1);
memset(val, '\0', strlen(str) + 1);
strcpy(val, str);
for (i = 0; val[i] != '\0'; i++) {
sum = sum + val[i];
}
return size % sum;
}
}
int main() {
int i;
char *str[9] = { "joy", "jam", "paula", "ulrich","cat", "act","yoj", "vij", "jiv" };
unsigned long key;
size_t size = 4542; // it may be anything just for test it is being used
for (i = 0; i < 9; i++) {
key = hash(str[i], size);
printf("\nkey[%ld]:val[%s]", key, str[i]);
}
return 1;
}
答案 0 :(得分:3)
是的,它可以,因为您的哈希函数编写得非常糟糕 - 它返回所有字符串字符的常量'size'变量模和。
问题是ASCII码'c'+'a'+'t'的总和等于'j'+'a'+'m'(等于312)所以你得到的值相同为你的'哈希'。
您可以为anagram表使用“普通”(例如多项式)哈希函数,但使用排序字符串 - 这将是最简单的方法。
对于另一种方法,您可以计算字符串中每个字母的出现次数(直方图)和散列(或只是按原样存储)。
我建议你对这个主题做一些研究,因为这是一个非常常见的任务。
此外,您可以对字符串进行排序,让unordered_set<string>
为您完成工作。
答案 1 :(得分:2)
好吧,你出错了。让我们看看你的算法。你正在做的是基本上总结字符串元素的ASCII值,并返回相对于总和的固定值的模数结果。但是果酱可能会出现同样的情况。
根据ASCII table详细说明,
j == 106
a == 97
m == 109
和
c == 99
a == 97
t == 116
这两个词最终的总和结果为312
。
现在按你的算法,
4542 % 312
假设给出常量值,对吗?这就是它所给予的。
现在,不要"sad"
,
s == 115
a ==97
d == 100
也提出了312
。
那就是说,我看到你的函数中定义了一个局部变量unsigned long hash_val = 5381;
,但没有使用它。
答案 2 :(得分:0)
您的哈希函数存在许多问题:
for (j = 0; j < 9; j++)
循环完全没用。return size % sum;
应该是return sum % size;
,因此返回值可以用作大小为size
的哈希表的索引。事实上,如果size % sum
碰巧计算到sum
,0
会调用未定义的行为,这需要一个非常长的字符串(> 16MB),但这是可能的。这是一个改进的哈希函数:
#include <limits.h>
// constraints: str != NULL, size > 0
size_t hash(const char *str, size_t size) {
size_t sum = 5381; // initial salt
while (*str != '\0') {
// rotate the current sum 2 places to the left
sum = (sum << 2) | (sum >> (CHAR_BIT * sizeof(sum) - 2));
// add the next character value
sum += (unsigned char)*str++;
}
return sum % size;
}