K& R的6.6节讨论了使用链表的哈希表。
简而言之,哈希表是一个指针数组。指针指向链表。链表是一个结构,如下所示:
struct nlist { /* table entry: */
struct nlist *next; /* next entry in chain */
char *name; /* defined name */
char *defn; /* replacement text */
};
名称经过哈希处理,此哈希值确定表中的索引。然后,本章将显示将名称/ defn对添加到表中的代码:
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;
进行插入技巧的好处是什么?
答案 0 :(得分:2)
在链式哈希中,通常在前面添加新元素,这就是为什么np始终是哈希表中列表的头部。它有点使用缓存局部性,也就是说,最近访问的那个可能会被再次访问。
此外,您的更改无法正常工作,因为它只是将np添加到哈希列表的下一个元素,但是之后的所有元素都将丢失。
答案 1 :(得分:1)
原因是地点。
在代码中,在哈希数组列表的第一个列表中插入一个新节点。当hashtab [hashval]为null(在第一个时)时,您的建议会导致分段错误,除非您在if语句中检查此情况。代码在第一时添加而不用担心这种情况。