2017-04-11 43 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

相關問題