我不明白为什么我的程序SEG故障在此行:if ((**table->table).link == NULL){
我似乎对此有malloc-edmem内存,我尝试使用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);
}
您的标签作品如下:您有bins
垃圾箱,每个垃圾箱都是键/值对的链接列表。垃圾箱中的所有项目都共享相同的哈希代码模型。
创建或初始化哈希表时,您可能已经创建了垃圾箱表,类似的东西:
table->table = malloc(table->bins * sizeof(*table->table);
for (size_t i = 0; i < table->bins; i++) table->table[i] = NULL;
现在为什么会员table
有两颗星?
- "内在"星是指桌子将指针存储在节点上,而不是节点本身。
"外部"开始是分配内存的手柄。如果您的哈希表尺寸固定,例如始终使用256个垃圾箱,则可以将其定义为:
struct node_s *table[256];
如果您通过此数组,它将变成(或"衰减")指向其第一个元素的指针,即
struct node_s **
,就像您从malloc
中获得的数组一样。- 您可以通过链接列表访问L´BINS的内容,而链接列表的负责人
i
为table->table[i]
。
您的代码还有其他问题:
您想用
(table->table)++
实现什么?这将使分配的内存点的句柄不是第一个元素,而是下一个元素。完成此操作后,*table->table
现在将处于正确的节点,但是您将丢失原始手柄,您必须保留,因为当您清理哈希表时,必须稍后将其传递给free
。不要失去分配的内存!改用另一个本地指针。您创建一个本地节点
n
,然后在链接列表中使用指向该节点的指针进行链接。但是节点n
将在您离开功能后将消失,链接将是"陈旧":它将指向无效的内存。您还必须使用malloc
为节点创建内存。
您的有表格的简单实现可能是:
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
函数不是标准的,而是广泛可用。它还创建了新的内存,您必须以后释放,但是它可以确保字符串" live"(仍然有效)在您结核哈希表之后。)
请不要在代码中有几颗星星。如果一颗恒星太少,它在hash_t
中,您已经输入了指针性质。