我正在尝试在C中编写一个简单的哈希表,并且在使用显示为main()
的代码进行测试时,我得到了一个非常奇怪的段错误。
设计:我有一个哈希表,其底层数组大小为10,000。我持有一个双指针指向struct node_t
(或node
)指针数组的开头。当我想在哈希表中put()
时,我会检查相应位置的node
元素是否为NULL
。如果是,我创建一个新节点来填充该点,否则,如果存在冲突,我会从冲突节点构建链接列表。
情景:在main()
中,我正在尝试将put()
数字3328放入哈希表中。相反,程序段错误。这对我没有意义,因为之前的put()
工作正常,你可以清楚地看到我将所有初始指针设置为NULL。据我所知,引用哈希表位置3328的指针没有设置为NULL,因为当我在put()
函数中取消引用它时,就是它的段错误。我的主要功能看起来应该将所有指针设置为NULL,尽管...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int TABLE_SIZE = 10000;
typedef struct node_t {
int key;
int value;
struct node_t* next;
} node;
node** table;
inline node** get_node_address(int key) {
key = (key > -key ? key : -key) % TABLE_SIZE;
return (node**) (table + key * sizeof(node*));
}
inline node* new_node(int key, int value) {
node* n = malloc(sizeof(node));
n->key = key;
n->value = value;
n->next = NULL;
return n;
}
void put(int key, int value) {
node** n = (node**) get_node_address(key);
node* iterator = (node*) *n;
if (*n == NULL) {
*n = new_node(key, value);
} else {
while (iterator->next != NULL)
iterator = iterator->next;
iterator->next = new_node(key, value);
}
}
int* get(int key) {
node* iterator = (node*) *get_node_address(key);
while (iterator != NULL && iterator->key != key) {
iterator = iterator->next;
}
if (iterator == NULL)
return NULL;
else
return &(iterator->value);
}
int main() {
printf("Starting..\n");
int i;
table = malloc(sizeof(node*) * TABLE_SIZE);
memset(table, 0, sizeof(node*) * TABLE_SIZE);
for (i = 0; i < TABLE_SIZE; i++) {
table[i] = NULL;
printf("setting %x\n", &table[i]);
}
printf("before bad: %x\n", *get_node_address(3327));
printf("bad address: %x\n", *get_node_address(3328));
printf("last address: %x\n", table + sizeof(node*) * TABLE_SIZE);
printf("Hashing...\n");
put(3328, 3338);
printf("%d", *get(3328));
return 0;
}
答案 0 :(得分:4)
至少有一个问题:
inline node** get_node_address(int key) {
key = (key > -key ? key : -key) % TABLE_SIZE;
return (node**) (table + key * sizeof(node*)); /* <---- */
}
你不能乘以key
。由于指针算法在C中的工作方式,table + key
会产生key
个元素。
答案 1 :(得分:0)
上面的代码可以简化很多:
void put(int key, int value) {
node **n = get_node_address(key);
for (n = get_node_address(key); *n; n = &(*n)->next) {;}
if(*n == NULL)
*n = new_node(key, value);
}
int* get(int key) {
node **n;
for (n = get_node_address(key); *n; n = &(*n)->next) {
if (n->key == key) break;
}
if(*n == NULL)
return NULL;
else
return &(*n)->value;
}