【问题标题】:I don't understand the hash tables example in K&R我不明白 K&R 中的哈希表示例
【发布时间】:2016-01-15 18:35:50
【问题描述】:

这是 K&R 书中哈希表示例中的安装函数:

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;
}

我不明白line np->next = hashtab[hasvall] 我认为使用变量 np->next 的原因是为了在表中放入两个具有相同哈希值的字符串,但结果是每个哈希值只有一个名称。

此外,我似乎无法理解函数查找,以及 for 中的“AFTERTHOUGHT”部分(因为我认为 talbe 中的每个结构只有一个值:

/* lookup: look for s in hashtab */
struct nlist *lookup(char *s)
{
    struct nlist *np;
    for (np = hashtab[hash(s)]; np != NULL; np = np->next)
        if (strcmp(s, np->name) == 0)
            return np; /* found */
    return NULL; /* not found */
}

我错过了什么?

【问题讨论】:

  • 哈希表存储每个桶的值的链接列表。 hashtab[hashval] 是该列表的头指针。节点被插入到前面,所以np 是新的头。 lookup 函数只是遍历列表。
  • 看起来chaining 用于解决多个值碰巧散列到散列表中的同一位置时的冲突。
  • @MOehm 我不明白它是如何变成链表的,据我了解,每次安装与另一个名称具有相同哈希值的名称时,它都会删除姓氏,并将 np->next指向自己,然后,查找对我也没有意义。
  • np->next = hashtab[hashval]; hashtab[hashval] = np; 并不意味着np 指向它自己。第一条语句使(当前未连接的)新节点的下一个链接成为当前头指针。第二个语句使新节点成为新头,因此列表变为:hashtable[hv] → 新节点 → 旧列表。当hashtable[hv](以及旧列表)之前为NULL 时,新节点现在是列表中的唯一节点。如果不是NULL,则旧内容现在从新节点的下一个指针链接。
  • 您可以按照自己的方式管理哈希表中的冲突。在这里,您使用哈希来查找表中的位置,并将搜索衰减到具有相同哈希值的元素的链表。

标签: c kernighan-and-ritchie


【解决方案1】:

每个值只能有一个键(名称),但两个或多个键可以具有相同的哈希值。 np->next = hashtab[hashval] 将新的hashval 添加到链接列表中。然后查找遍历列表,直到匹配到键(名称)。

【讨论】:

    【解决方案2】:
        np->next = hashtab[hashval]; 
        hashtab[hashval] = np;
    

    这两行不是替换旧条目,而是添加到旧条目中。

    hashtab[hashval]-> existing_node 变为
    hashtab[hashval]-> np -(next)-> existing_node

    正如@Bo Persson 在 cmets 中提到的,这称为“chaining”。

    鉴于此结构,lookup 函数可以正确检查链中每个节点的名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-15
      • 2021-03-02
      • 1970-01-01
      • 2019-06-14
      • 2014-08-18
      • 2021-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多