【问题标题】:C list table from book K & R来自书籍 K & R 的 C 列表表
【发布时间】:2016-08-03 22:01:18
【问题描述】:

K&R 的第 6.6 节讨论了使用链表的哈希表。

简而言之,哈希表是一个指针数组。指针指向一个链表。链表是一个结构,如下所示:

struct nlist {             /* table entry: */
    struct nlist *next;    /* next entry in chain */
    char *name;            /* defined name */
    char *defn;            /* replacement text */
};

名称是经过散列的,这个散列决定了表中的索引。然后本章显示了将名称/定义对添加到表中的代码:

struct nlist *install(char *name, char *defn) {
    struct nlist *np;
    unsigned hashval;
    if ((np = lookup(name)) == NULL) { /* not found */
        np = (struct nlist *) malloc(sizeof(*np));
        if (np == NULL || (np->name = strdup(name)) == NULL)
            return NULL;
        hashval = hash(name);
        np->next = hashtab[hashval];
        hashtab[hashval] = np;
    } else /* already there */
        free((void *) np->defn); /*free previous defn */
    if ((np->defn = strdup(defn)) == NULL)
        return NULL;
    return np;
}

除了以下两行之外,一切都有意义:

np->next = hashtab[hashval];
hashtab[hashval] = np;

我的问题是他们为什么不直接将其分配给next 而不是插入它?即,

hashtab[hashval]->next = np; 
np->next = NULL;

使用插入技巧有什么好处?

【问题讨论】:

  • 要找到链表的末尾,必须遍历next指针,直到找到最后一个节点。
  • hashtab[hashval]是第hashval链表的头指针,所以hashtab[hashval]->next = np这样的代码会失去头指针,除非你在编码之前做了一些迭代
  • 不要将malloc 和朋友或void * 的结果转换为/从C 中的指针转换!并使用至少涵盖 C99 的书 - 更好的标准 C。

标签: c


【解决方案1】:

在链式哈希中,您通常在前面添加新元素,这就是为什么 np 始终是哈希表中列表的头部。这是一种缓存局部性的使用,即最近访问的一个很可能再次被访问。

此外,您的更改不会起作用,因为它只是将 np 添加到哈希列表的下一个元素,但之后的所有元素都将丢失。

【讨论】:

  • 也许这是一个原因。
【解决方案2】:

原因是地方性。

在代码中,一个新节点插入到哈希数组列表的第一个列表中。您的建议当 hashtab[hashval] 为空时(首先)会导致分段错误,除非您在 if 语句中检查这种情况。代码首先添加而无需担心这种情况。

【讨论】:

    猜你喜欢
    • 2015-11-11
    • 1970-01-01
    • 2010-10-08
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多