尝试使用smdb算法制作哈希表(因为我听说不尝试自己编写哈希表是明智的。)我确信我做错了。我提到我是C的新手吗?
我的hashFunction()%size首次在第一次调用时返回35之类的数字,然后在第二次调用,第三次调用,第四次调用...时返回65无限广告。我只是将这些数字用作任意例子。在尝试使用调试器解决问题之后,我注意到hashFunction返回了不同的long,但它们都以相同的最后2个数字结束......就像这样......
4460735 4526335 4591935
所以我想这就是为什么当我散列%size时,我每次都得到相同的输出。这违背了均匀分布的密钥的想法,对吗?
请放轻松。我知道SO上的野蛮人是多么可以。
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
char* str;
struct node* next;
}
node;
void insertItem(char* number, node** list);
unsigned long hashFunction(char* str);
int main(void)
{
int size = 100;
int index = 0;
node* buckets[size];
for (int i = 0; i < size; i++)
{
char c = i + 'A';
index = hashFunction(&c) % size;
insertItem(&c, &buckets[index]);
}
}
void insertItem(char* str, node** list)
{
node* newItem = malloc(sizeof(node));
newItem->str = str;
newItem->next = *list;
*list = newItem;
}
unsigned long hashFunction(char* str)
{
//sdbm hash function adapted (incorrectly?) from here: http://www.cse.yorku.ca/~oz/hash.html
unsigned long hash = 0;
int c;
while ((c = *str++))
hash = c + (hash << 6) + (hash << 16) - hash;
return hash;
}
答案 0 :(得分:2)
问题是你对不在字符串上的字符进行测试。
如果您使用真实字符串提供算法,那么您将获得更重要的信息。例如,使用以下代码更改代码:
char mystring[] = "Any string will do !";
for (int i = 0; i < size; i++)
{
mystring[0] = i; // simple hack to change the string a bit, well ... a byte ;)
index = hashFunction(mystring) % size;
insertItem(mystring, &buckets[index]);
}
如果您打印index
,您将获得更合适的索引。
编辑:
真正的问题是你的哈希函数被设计为获得一个C字符串作为参数(一个指向缓冲区的char *必须以空终止,即以'\0'
结尾)。当您给出单个字符的地址时,第一个取消引用是可以的,但是使用指向不是真正分配对象的下一个地址(在++
之后)是undefined behavior。 / p>
致谢:请参阅moooeeeep answer和评论。
答案 1 :(得分:2)
散列函数需要一个指向空终止字符串的指针作为输入参数。您将指针传递给单个字符。然后,该函数迭代无效内存,直到它到达一个随机空字节。
char arr[] = "Hello World";
index = hashFunction(arr) % size;
您需要将指针传递给字符串。例如:
size
还可以考虑将def springSecurityService
设置为素数以增加随机性。进一步阅读: