我不明白为什么我的程序在以下行出现段错误:if ((**table->table).link == NULL){
我似乎为它分配了malloc的内存,并尝试使用gdb进行查看。 *table->table
可以访问并且不能为NULL,但是**table->table
无法访问。
hash_t的定义:
struct table_s {
struct node_s **table;
size_t bins;
size_t size;
};
typedef struct table_s *hash_t;
void set(hash_t table, char *key, int value){
unsigned int hashnum = hash(key)%table->bins;
printf("%d \n", hashnum);
unsigned int i;
for (i = 0; i<hashnum; i++){
(table->table)++;
}
if (*(table->table) == NULL){
struct node_s n = {key, value, NULL};
struct node_s *np = &n;
*(table->table) = malloc(sizeof(struct node_s));
*(table->table) = np;
}else{
while ( *(table->table) != NULL){
if ((**table->table).link == NULL){
struct node_s n = {key, value, NULL};
struct node_s *np = &n;
(**table->table).link = malloc(sizeof(struct node_s));
(**table->table).link = np;
break;
}else if (strcmp((**table->table).key, key) == 0){
break;
}
*table->table = (**(table->table)).link;
}
if (table->size/table->bins > 1){
rehash(table);
}
}
}
我从这里打电话给我
for (int i = 0; i < trials; i++) {
int sample = rand() % max_num;
sprintf(key, "%d", sample);
set(table, key, sample);
}
答案 0 :(得分:0)
您的哈希表的工作方式如下:您有bins
个bin,每个bin是键/值对的链接列表。箱中的所有项目均以箱数为模,共享相同的哈希码。
创建或初始化哈希表时,您可能已经创建了bins表,如下所示:
table->table = malloc(table->bins * sizeof(*table->table);
for (size_t i = 0; i < table->bins; i++) table->table[i] = NULL;
现在成员table
为什么有两颗星?
“外部”开始是分配的内存的句柄。如果您的哈希表是固定大小的,例如始终具有256个bin,则可以将其定义为:
struct node_s *table[256];
如果您将此数组传递给周围,它将变成(或“衰减为”)指向其第一个元素struct node_s **
的指针,就像从malloc
获得的数组一样。
i
是table->table[i]
。 您的代码还有其他问题:
您想用(table->table)++
实现什么?这将使分配的内存句柄不指向第一个元素,而是指向下一个元素。经过该哈希数次之后,*table->table
现在将位于正确的节点上,但是您将丢失必须保留的原始句柄,因为在稍后清理时必须将其传递给free
哈希表。不要丢失分配内存的句柄!改用另一个本地指针。
您创建一个本地节点n
,然后在链接列表中使用指向该节点的指针进行链接。但是,节点n
将在您离开函数后消失,并且链接将“陈旧”:它将指向无效的内存。您还必须使用malloc
为节点创建内存。
has表的简单实现可能是:
void set(hash_t table, char *key, int value)
{
unsigned int hashnum = hash(key) % table->bins;
// create (uninitialised) new node
struct node_s *nnew = malloc(sizeof(*nnew));
// initialise new node, point it to old head
nnew->key = strdup(key);
nnew->value = value;
nnew->link = table->table[hashnum];
// make the new node the new head
table->table[hashnum] = nnew;
}
这使新节点成为链接列表的头部。这是不理想的,因为如果您覆盖项目,则会找到新项目(很好),但是旧项目仍将在表中(不好)。但是,正如他们所说,这是留给读者的练习。
(strdup
函数不是标准函数,但用途广泛。它还会创建新的内存,您必须稍后释放该内存,但可以确保在拥有字符串之后,字符串“ lives”(仍然有效)选择了哈希表。)
请不要在代码中有多少颗星星。如果一颗恒星太少,则位于hash_t
中,在那里您已经抛弃了指针的性质。