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