10. Hash Maps (a.k.a. Dictionaries / Hash Tables)
🧸 ELI5: A hash map is a coat check at a party. You hand over your coat, they give you ticket #42. Later, you show ticket #42, and they go directly to hook #42 and grab your coat — no searching through every coat in the building.
🌍 Real life: Your phone's contacts app — you type a name, and it instantly finds the number (it's not scanning every contact one by one). A locker with your name mapped to locker #17.
📝 Pseudocode:
map = {}
map["Alice"] = "555-1234"
map["Bob"] = "555-5678"
print(map["Alice"]) // instantly -> "555-1234"
🐹 Go:
package main
import "fmt"
func main() {
contacts := make(map[string]string)
contacts["Alice"] = "555-1234"
contacts["Bob"] = "555-5678"
number, found := contacts["Alice"]
if found {
fmt.Println(number) // 555-1234
}
}
🇨 C (deep dive: real-life-c-guide.md §18.2) — C has no built-in map, so this coat-check counter is the actual mechanism Go's map and Python's dict hide from you: a hash function plus separate-chaining buckets:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUCKETS 16
typedef struct HTEntry {
char *key, *value;
struct HTEntry *next;
} HTEntry;
static HTEntry *buckets[BUCKETS];
static unsigned long djb2(const char *s) { // Section 18.2's hash function
unsigned long hash = 5381;
int c;
while ((c = (unsigned char)*s++)) hash = ((hash << 5) + hash) + (unsigned long)c;
return hash;
}
void ht_set(const char *key, const char *value) {
unsigned long idx = djb2(key) % BUCKETS;
for (HTEntry *e = buckets[idx]; e; e = e->next) {
if (strcmp(e->key, key) == 0) { free(e->value); e->value = strdup(value); return; }
}
HTEntry *e = malloc(sizeof(HTEntry));
e->key = strdup(key);
e->value = strdup(value);
e->next = buckets[idx]; // insert at the head of this ticket number's coat rack
buckets[idx] = e;
}
const char *ht_get(const char *key) {
unsigned long idx = djb2(key) % BUCKETS;
for (HTEntry *e = buckets[idx]; e; e = e->next) {
if (strcmp(e->key, key) == 0) return e->value;
}
return NULL;
}
int main(void) {
ht_set("Alice", "555-1234");
ht_set("Bob", "555-5678");
const char *number = ht_get("Alice");
if (number) printf("%s\n", number); // 555-1234
return 0;
}
(compile with -std=gnu17, not strict -std=c17 — strdup is POSIX, hidden under strict ANSI on Linux/glibc; see the C guide's §2.2 note.)
⏱️ Complexity: Insert/lookup/delete = O(1) average — the magic of "hashing" the key straight to its slot, like ticket #42 pointing straight to hook #42.