0

我正在尝试用 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;
}
4

2 回答 2

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-th 元素。

于 2012-04-14T16:14:52.947 回答
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; 
}
于 2012-04-14T17:16:52.060 回答