【发布时间】: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,则旧内容现在从新节点的下一个指针链接。 -
您可以按照自己的方式管理哈希表中的冲突。在这里,您使用哈希来查找表中的位置,并将搜索衰减到具有相同哈希值的元素的链表。