Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Table lookup install function from k&r

Tags:

c

hashtable

Section 6.6 of K&R discusses a hash table using a linked list.

In short, a hash table is an array of pointers. The pointers point to a linked list. The linked list is a struct that looks like:

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

The name is hashed, and this hash determines the index in the table. The chapter then shows code to add a name/defn pair to the table:

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

Everything makes sense except for the following 2 lines:

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

When I try to understand this, I keep coming to the conclusion that the list now links back to itself and if you try to traverse the linked list it will be like a dog chasing its own tail. I would expect the code to set np->next to NULL.

What am I not understanding? How come this code works ?

like image 767
c_newb Avatar asked Aug 10 '11 17:08

c_newb


2 Answers

It results in the new value being inserted at the beginning of the list.

So it goes from:

hashtab[hashval]   -->  original_list

to:

hashtab[hashval]   -->  original_list
np->next           -->  original_list

to:

hashtab[hashval]  -->  *np
        np->next  -->  original_list

The golden rule is, if linked-list code doesn't make sense, always draw out a diagram!

like image 176
Oliver Charlesworth Avatar answered Oct 16 '22 16:10

Oliver Charlesworth


hashtab[hashval] is a pointer, not a value. It is a pointer to the address in memory where the first element of that particular row in the pointer table (static struct nlist *hashtab[HASHSIZE]) resides. np and np->next are also pointers. So here is what happens in these two lines: First line: The pointer of the first element in that row of the table is copied into np->next. np->next now points at the address in memory where the first element of that row used to point. Second line: The pointer to the address in memory where the new *np resides is now copied into the pointer variable hastab[hashval]. hastab[hashval] now once again becomes the pointer to where the first element of that table row resides. So, just as Oli wrote, the new *np is inserted at the beginning of that particular row in the table.

like image 2
Contributor123 Avatar answered Oct 16 '22 15:10

Contributor123