【问题标题】:K&R Table Lookup CodeK&R 表查找代码
【发布时间】:2013-02-25 11:31:39
【问题描述】:

尝试理解以下代码,用于实现 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 重新初始化它,它不会总是为 NULL 吗?还是 malloc 只是简单地分配内存而不会弄乱之前分配给 np 的值?如果是这种情况,那么如果 np 在初始 if 语句中已经这样做了,为什么还要再次检查 np 是否为 NULL 呢?

当谈到np->next 代码时,我完全迷失了。为什么 np->next 似乎是指自己?

这里是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 */
};

【问题讨论】:

  • 您可能希望从较低的位置开始。这是一个更有经验的例子。

标签: c


【解决方案1】:
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 = hashtab[hashval];
    hashtab[hashval] = np;

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

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

【讨论】:

  • 谢谢,这几乎可以解决所有问题。然而,关于指向自身的指针,这很奇怪,因为这本书介绍了这个用于迭代链表的习语:for (ptr = head; ptr != NULL; ptr = ptr->next)。看起来这会创建一个无限循环,因为指针永远不会指向 NULL。我错过了什么吗?
  • 嗯,我和你一样困惑。我想我必须看到整个事情才能理解。
  • 我用lookup()函数更新了代码,以防你感兴趣。
  • @user1427661 我更新了我的答案,所以它实际上是正确的,如果你有兴趣:-)
  • 太棒了!现在一切都在一起了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-24
  • 2014-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
相关资源
最近更新 更多