[英]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.