5

here is the install function from the hash tables example from K&R's book:

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

I don't understand the line np->next = hashtab[hasvall] I thought the reason to have the variable np->next is for putting in the table two string with the same hash value, but the outcome from this is having only one name for every hash value.

Furthermore I cannot seem to understand the function lookup, and the "AFTERTHOUGHT part in the for(because I think there is only one vaule to every struct in the 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 */
}

What am I missing?

Bar K
  • 89
  • 1
  • 7
  • 3
    The hashtable stores a linked list of values for each bucket. `hashtab[hashval]` is the head pointer of that list. The nodes are inserted at the front so that `np` is the new head. The `lookup` function just walks the list. – M Oehm Jan 15 '16 at 18:39
  • 3
    It looks like [chaining](https://en.wikipedia.org/wiki/Hash_table#Collision_resolution) used to resolve collisions when more than one value happens to hash to the same position in the hash table. – Bo Persson Jan 15 '16 at 18:42
  • @MOehm I dont understand how this becomes into a linked list, in my understaning every time a name with a same hash as another name is installed, it deletes the last name, and puts np->next to point to himself, Then, lookup doesnt make sence to me either. – Bar K Jan 15 '16 at 18:43
  • 1
    `np->next = hashtab[hashval]; hashtab[hashval] = np;` does not mean that `np` points to itself. The first statement makes the (currently unattached) new nodes's next link the current head pointer. The second stetement makes the new node the new head, so that the list goes: `hashtable[hv]` → new node → old list. When `hashtable[hv]` (and therefore the old list) was `NULL` before, the new node is now the only node in the list. If it wasn't `NULL`, the old contents are now linked from the new node's next pointer. – M Oehm Jan 15 '16 at 18:49
  • You can manage collision in hashtables, the way you want. Here, you use a hash to find a position in the table and decay the search to a linked list of elements with the same hash value. – Jean-Baptiste Yunès Jan 15 '16 at 18:57
  • @MOehm Thank you all very much! – Bar K Jan 15 '16 at 19:08

2 Answers2

3

You can have only one key (name) for every value, but two or more keys can have the same hash. np->next = hashtab[hashval] adds the new hashval to the linked list. Lookup then iterates through the list until the key (name) is matched.

AShelly
  • 34,686
  • 15
  • 91
  • 152
csteel
  • 428
  • 1
  • 3
  • 14
2
    np->next = hashtab[hashval]; 
    hashtab[hashval] = np;

These two lines do not replace the old entry, they add to it.

hashtab[hashval]-> existing_node becomes
hashtab[hashval]-> np -(next)-> existing_node

As @Bo Persson mentions in the comments, this is called "chaining".

Given this structure, the lookup function correctly checks the names of each node in the chain.

AShelly
  • 34,686
  • 15
  • 91
  • 152