2017-04-11 46 views
2

试图使用smdb算法做一个哈希表(因为我听到这是明智的,不要试图写我自己的。)我敢肯定,我是完全错误的。我提到我是C新手吗?C smdb散列值%tableSize重复计算为相同的值? (用不同的输入。)

我的hashFunction()%size在第一次调用时返回一个数字,如35,然后在第二次调用,第三次调用,第四次调用时返回65,并返回65。我只是将这些数字用作任意的例子。试图用调试器来弄明白后,我发现散列函数将返回不同的多头,但它们使用相同的最后2个数字全部结束......像这样......

4460735 4526335 4591935

所以我想这是为什么当我散列%大小时,每次都会得到相同的输出结果。这违背了均匀分布键的想法,对吧?

请随便找我。我知道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

也许使用质数作为'size'可以帮助:http://stackoverflow.com/q/3980117/1025391/HTTP:// stackoverflow.com/q/1145217/1025391? – moooeeeep

+1

啊 - 这不是真正的问题。现在我看... – moooeeeep

+0

@moooeeeep感谢您的提示,但!我以前读过,你说得对,我会在将来考虑。 –

回答

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

积分:见moooeeeep answer,和评论。

+0

嗨,谢谢你的回复。它实际上只是以2个桶结束,其中1个桶只有1个列表项,其余的都在第2桶。我会用更长的字符串再试一次,看看它是如何发展的,就像你建议的那样。 –

+0

当我用你的代码打印索引时,我得到一个65,然后很多35,然后没有那么多7.问题是你的数据类型是char不是char * – neuro

+0

当我替换char c = i +'A'与你的建议,(并删除&我的函数参数使用c),我得到这个错误:“添加'int'字符串不附加到字符串[-Werror,-Wstring-plus-int]” –

2

散列函数需要一个指向以空字符结尾的字符串作为输入参数的指针。您将指针传递给单个字符。该函数然后迭代无效内存,直到它到达一个随机空字节。

char c = i + 'A'; 
index = hashFunction(&c) % size; 

您需要将指针传递给字符串。例如:

char arr[] = "Hello World"; 
index = hashFunction(arr) % size; 

也可以考虑设置你的size为增加随机性素数。进一步阅读:

+0

非常有帮助:)我喜欢你解释它的方式,并提供了一些额外的帮助,超出了我的问题范围,我会将它标记为答案,但神经指出我的监督第一:P –

+0

@moooeeeep:你是对的类型,但我不知道通过随机存储器的迭代。我的C有点生锈... – neuro

+0

@neuro当指针在循环条件[行为未定义](https://en.wikipedia.org/wiki/Undefined_behavior)中增加并取消引用时。取消引用不指向对象的指针是不允许的,无论目前的内存是什么值。没有分段故障被触发只是一个巧合。 – moooeeeep

相关问题