簡體   English   中英

發生沖突后在哈希表中實現鏈接時出現分段錯誤

[英]Segmentation fault while implementing chaining in hash table after collisions occur

我正在嘗試實現鏈接(哈希表中的沖突解決技術)。 我的程序對於大多數測試用例都可以正常工作。

這是我的程序(它很大,但是我知道它在哪里失敗。因此,如果需要,您可以跳過此部分。):

#include<stdio.h>
#include<stdlib.h>

struct LinkedListNode
{
    int data;
    struct LinkedListNode *next;
};

struct LinkedListNode* getNewNode()
{
    // I don't need to cast the malloc in c
    return malloc(sizeof(struct LinkedListNode));
}

struct LinkedListNode* insertAtBeginning(struct LinkedListNode** hashTable, int index, int data)
{
    struct LinkedListNode* newNode = getNewNode(); // the new node
    newNode->data = data;
    newNode->next = NULL; // for now I can put the next to be null

    // check if the block is containing null or not
    if (hashTable[index] == NULL)
    {
        // now just insert the new element at beginning
        hashTable[index] = newNode;
        return hashTable[index]; // returning the new address of the block
    }

    // if collisions occur
    struct LinkedListNode* blockListAddress = hashTable[index]; // the address pointing to first node of linked list
    newNode->next = blockListAddress; // storing the address of block in the next of the new linkedlist
    hashTable[index] = newNode; // changing the block address to the address of new node (as we have to insert in beginning)
    return hashTable[index];
}

struct LinkedListNode* searchMe(struct LinkedListNode** hashTable, int index, int key)
{
    struct LinkedListNode* res = NULL;
    struct LinkedListNode* temp = hashTable[index];

    if (temp == NULL)
        return NULL;

    // if we just have one element in the block then the while loop below won't get executed
    // because here condition is temp->next which will be null, thus here I have written if condition
    if (hashTable[index] != NULL && hashTable[index]->data == key)
    {
        return hashTable[index];
    }

    // if not null then traverse through linked list
    while (temp != NULL)
    {
        printf("\nTEMP = %d", temp);
        if (key == temp->data)
            res = temp;
        printf("\ntemp->data=%d\n", temp->data);
        temp = temp->next;
    }
    return res;
}

int hashFunction(int num)
{
    return num%10;
}

int main()
{
    int n;
    printf("\nEnter elements to be stored\n");
    scanf("%d", &n);

    // declaring the hashTable of size n (i.e. size of input elements), its gonna have pointers to LinkedListNode
    struct LinkedListNode** hashTable = malloc(n*sizeof(struct LinkedListNode*)); // I have given memory to the table, now I even need to give memory to the elements in the table
    int i;
    for (i = 0; i < n; ++i)
    {
        hashTable[i] = NULL;
    }

    int d;
    printf("\nEnter the elements in array\n");
    for (i = 0; i < n; ++i)
    {
        scanf("%d", &d);
        int hashedValue = hashFunction(d);
        hashTable[hashedValue] = insertAtBeginning(hashTable, hashedValue, d);
    }

    int key;
    printf("\nEnter the element you want to search for\n");
    scanf("%d", &key);
    int ind = hashFunction(key);
    struct LinkedListNode* res = searchMe(hashTable, ind, key);

    if (res == NULL)
    {
        printf("\nNot found\n");
    }
    else
    {
        printf("\n%d is found\n", res->data);
    }
}


// time complexity in worst case for searching = O(n),
// average case t.c = O(1+alpha), where alpha = n/m
// n <- number of elements in hashtable
// m <- size of hashtable
// so alpha is 1 in this case
// thus average t.c = theta(1)

該程序為該測試用例提供了SIGSEGV

輸入要存儲的元素

輸入數組中的元素

21 32 565 784 445

輸入您要搜索的元素

565

溫度= 35383520

TEMP->數據= 445

溫度= 35383456

TEMP->數據= 565

分段故障(核心已轉儲)

調試后,我發現它在第56行拋出了段錯誤,即:

if (key == temp->data)

此行在以下代碼段中編寫:

while (temp != NULL)
{
    printf("\nTEMP = %d", temp);
    if (key == temp->data)
        res = temp;
    printf("\ntemp->data=%d\n", temp->data);
    temp = temp->next;
}

正如您在上面的失敗測試中所看到的那樣,while循環執行了3次(它應該只執行兩次,因為temp第三次指向null)。 而且,當它第三次執行時,它會在if (key == temp->data)的行上拋出段錯誤。

這意味着temp不是NULL ,甚至沒有data字段。 因此,插入時可能會出現問題(即,在插入newNode的下一個字段時可能不會設為NULL ,但我已妥善處理了該事情。)如果在插入時出現問題,則我的代碼應該失敗其他測試用例。 但是對於上面指定的測試用例,代碼只是失敗了。

例如,代碼通過了此測試用例:

[aupadhyay @ localhost c] $ ./a.out

輸入要存儲的元素

7

輸入數組中的元素

21 32 565 784 445 655 84

輸入您要搜索的元素

565

溫度= 8063248

TEMP->數據= 655

溫度= 8063216

TEMP->數據= 445

溫度= 8063152

TEMP->數據= 565

找到565

我只是無法弄清楚,為什么它不能通過提到的測試用例。

代碼在許多地方存在的問題是,您無法確保在索引hashTable時仍保持在最初分配的范圍內。

在您的示例中,數字565會生成5的hashedValue 。您僅在hashTable分配了5個元素, hashTable該元素覆蓋了0到4的范圍。 插入hashTable[5]將進入未定義行為的領域,並且您的代碼將崩潰。 當您輸入7個數字時,您不會遇到相同的問題,因為所有7個數字都會生成在0到6范圍內的hashedValue

由於您的hashFunction將僅返回0到9之間的數字,因此您可以聲明一個新變量以跟蹤hashTable的大小,並在輸入數字時對其進行擴展,或者預分配其最大大小。

struct LinkedListNode** hashTable = malloc(10*sizeof(struct LinkedListNode*)); // I
int i;
for (i = 0; i < 10; ++i)
{
    hashTable[i] = NULL;
}

從長遠來看,另一個選項會更有意義,因為如果您更改hashFunction ,它將可以適應。

您的問題在這里:您沒有正確初始化哈希表。 你寫了:

int i;
for (i = 0; i < n; ++i)
{
    hashTable[i] = NULL;
}

由於您的哈希表有10個存儲桶,因此它應為i <10。

當n == 5時,hashTable [5]未初始化並且具有垃圾。 當對545進行哈希處理時,它將作為下一個指針(而不是NULL)得到該垃圾。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM