DSA Notes
Implement and analyze separate chaining for hash collision resolution — linked lists at each bucket, performance analysis, load factor behavior, and practical considerations.
How Separate Chaining Works
In separate chaining, each slot (bucket) in the hash table holds a pointer to a data structure — typically a linked list — that stores all key-value pairs mapping to that index. When a collision occurs, the new element is simply appended (or prepended) to the list at that bucket.
| Index 0: | [7, "seven"] → [14, "fourteen"] → [21, "twenty-one"] → NULL |
| Index 1: | [1, "one"] → [8, "eight"] → NULL |
| Index 2: | [2, "two"] → NULL |
| Index 3: | NULL (empty bucket) |
| Index 4: | [4, "four"] → [11, "eleven"] → NULL |
| Index 5: | [5, "five"] → NULL |
| Index 6: | [6, "six"] → NULL |
Operations
Insert (key, value)
- Compute
index = h(key) - Search the chain at
table[index]for the key - If found, update the value
- If not found, prepend/append to the chain
Search (key)
- Compute
index = h(key) - Traverse the chain at
table[index] - Return value if key found, else "not found"
Delete (key)
- Compute
index = h(key) - Traverse the chain, find the node
- Remove the node from the linked list (standard list deletion)
Complete Python Implementation
C++ Implementation
Performance Analysis
Assuming a good hash function distributes n keys uniformly across m buckets:
Average chain length = n/m = α (load factor)
| Operation | Best Case | Average Case | Worst Case |
|---|---|---|---|
| Insert | O(1) | O(1) | O(n) — all keys in one chain |
| Search (success) | O(1) | O(1 + α/2) | O(n) |
| Search (failure) | O(1) | O(1 + α) | O(n) |
| Delete | O(1) | O(1 + α/2) | O(n) |
The O(1 + α) means: O(1) to compute the hash, plus traversing an average chain of length α.
When α = 1.0:
- Successful search: ~1.5 comparisons on average
- Unsuccessful search: ~2 comparisons
When α = 0.5:
- Successful search: ~1.25 comparisons
- Unsuccessful search: ~1.5 comparisons
Advantages of Separate Chaining
- Simple to implement — standard linked list operations
- Load factor can exceed 1.0 — chains just grow longer
- Deletion is straightforward — no tombstones or restructuring needed
- Graceful degradation — performance degrades linearly with load, no sudden cliff
- Dynamic — memory allocated per insertion (no wasted pre-allocated slots)
Disadvantages
- Poor cache performance — pointer chasing across non-contiguous memory
- Extra memory per entry — each node needs a next pointer (8 bytes on 64-bit)
- Memory fragmentation — nodes allocated individually on heap
- Slow for small tables — overhead of linked list outweighs benefit
Optimization: Chaining with Arrays Instead of Lists
Replace linked lists with dynamic arrays (vectors) per bucket for better cache locality:
This is what Python's dict actually does (sort of) — it trades linked-list pointer overhead for array-based storage with better spatial locality.
Java's Advanced Chaining (Tree Bins)
Java 8's HashMap converts a chain to a red-black tree when its length reaches 8:
| Chain length < 8 | Linked list (O(n) search within chain) |
| Chain length ≥ 8 | Red-black tree (O(log n) search within chain) |
| Chain length < 6 | Reverts to linked list (hysteresis) |
This ensures O(log n) worst case even with terrible hash distribution — a defense against hash-flooding attacks.
Real-World Applications
- Java HashMap, C++ unordered_map — both use chaining by default
- Database hash joins — build phase creates chained hash table of smaller relation
- Symbol tables in compilers — variable/function names stored with chaining
- Network packet classification — rule tables use chaining for multi-match
Key Takeaways
Separate chaining is the most intuitive collision resolution strategy: each bucket holds a list of collided elements. It is simple, deletion-friendly, and tolerates high load factors. The trade-off is cache performance and memory overhead from pointers. For most general-purpose applications (Java, C++ standard libraries), chaining remains the default choice due to its robustness and simplicity.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Separate Chaining.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Data Structures & Algorithms topic.
Search Terms
data-structures-algorithms, data structures & algorithms, data, structures, algorithms, hashing, chaining, separate chaining
Related Data Structures & Algorithms Topics