K& R表查找代码

时间:2013-03-10 05:07:25

标签: c

尝试理解K& R中讨论的简单散列查找算法的链表/结构实现的以下代码:

struct nlist *lookup(char *);
char *strdup(char *);
/* install: put (name, defn) in hashtab */
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 = (struct nlist *) malloc(sizeof(*np));
if语句将值lookup(name)赋给np后发生

。那么malloc任务有什么作用呢?它是否重新初始化了价值?如果是这样,那么下面这行是什么?

if ((np = lookup(name)) == NULL)

如果malloc重新初始化它,它不会总是为空吗?或者malloc是否只是简单地分配内存而不会弄乱先前分配给np的值?如果是这种情况,那么为什么如果np为NULL,如果它已经在初始if语句中执行了那么它为什么再次检查?

说到np->next代码,我完全迷失了。为什么np->接下来似乎是指自己?

以下是lookup()函数的代码:

/* 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 */
}

这是nlist结构:

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

1 个答案:

答案 0 :(得分:10)

if ((np = lookup(name)) == NULL)

做两件事。首先,它将lookup(name)的结果分配给np。其次,它测试该分配的结果,看它是否为NULL

如果if语句为真,则表示npNULL,因此它们会为malloc提供一个值。

现在,如果malloc无法分配内存,则返回NULLstrdup内部调用malloc,这就是下一行

的原因
if (np == NULL || (np->name = strdup(name)) == NULL)

确保刚刚发生的两次分配都成功。

你是对的,因为新分配的条目np->next指向自己。这就是他们如何表明清单的结尾。其他实现使用NULL来表示列表末尾。


编辑:我是个傻瓜,你让我说服你错了!

首先,哈希表如下所示:它是一个指向链表的指针表。数组中的索引是哈希值:

enter image description here

现在我们添加一个新条目:

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

hashtab[hashval]已经是具有相同哈希的条目列表的开头。它可能是NULL。此代码将新条目添加到列表的 front !因此,我们将新条目的next指针指向现有列表,并将哈希表设置为指向新条目,因此它现在是第一个。

enter image description here

他们将节点添加到列表的前面,以便插入是O(1)操作。