Skip to content
  • Hash Table · C

Hash Table

LearnViaNotes @learnvianotes· 2 min read

An array of buckets indexed by hash(key) % capacity. With a good hash function and a reasonable load factor, lookup, insert and delete are O(1) on average.

C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NBUCKETS 8

typedef struct Entry {
    char *key;
    int value;
    struct Entry *next;               /* separate chaining */
} Entry;

typedef struct { Entry *buckets[NBUCKETS]; size_t count; } Map;

unsigned long hash(const char *s) {   /* djb2 by Dan Bernstein */
    unsigned long h = 5381;
    for (; *s; s++) h = h * 33 + (unsigned char)*s;
    return h;
}

void map_put(Map *m, const char *key, int value) {
    size_t i = hash(key) % NBUCKETS;
    for (Entry *e = m->buckets[i]; e; e = e->next)
        if (strcmp(e->key, key) == 0) { e->value = value; return; }   /* update */
    Entry *e = malloc(sizeof *e);
    if (!e) exit(1);
    size_t n = strlen(key) + 1;
    e->key = malloc(n);
    if (!e->key) exit(1);
    memcpy(e->key, key, n);
    e->value = value;
    e->next = m->buckets[i];          /* insert at bucket head */
    m->buckets[i] = e;
    m->count++;
}

int *map_get(Map *m, const char *key) {
    for (Entry *e = m->buckets[hash(key) % NBUCKETS]; e; e = e->next)
        if (strcmp(e->key, key) == 0) return &e->value;
    return NULL;
}

void map_free(Map *m) {
    for (int i = 0; i < NBUCKETS; i++)
        for (Entry *e = m->buckets[i], *next; e; e = next) {
            next = e->next;
            free(e->key);
            free(e);
        }
}

int main(void) {
    Map m = {0};
    const char *words[] = {"the", "cat", "sat", "on", "the", "mat", "the", "cat"};
    for (int i = 0; i < 8; i++) {
        int *c = map_get(&m, words[i]);
        if (c) (*c)++; else map_put(&m, words[i], 1);
    }
    const char *probe[] = {"the", "cat", "mat", "dog"};
    for (int i = 0; i < 4; i++) {
        int *c = map_get(&m, probe[i]);
        printf("%s: %d\n", probe[i], c ? *c : 0);
    }
    printf("distinct words: %zu\n", m.count);
    map_free(&m);
    return 0;
}
Output
the: 3
cat: 2
mat: 1
dog: 0
distinct words: 5
Collision strategyHowNotes
Separate chainingEach bucket is a linked listSimple; degrades gracefully; extra pointers
Linear probingTry i + 1, i + 2, … in the arrayCache-friendly; needs tombstones for delete; clustering
Quadratic / double hashingProbe with a step that grows or comes from a 2nd hashLess clustering

What makes a good hash function?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report