Hash Tables: Hash Functions, Separate Chaining & Open Addressing
Hash Tables: Hash Functions, Separate Chaining & Open Addressing
The Hash Table (Hash Map) is arguably the single most important data structure in real-world software engineering. By translating arbitrary keys (like strings, objects, or URLs) into array indices using a Hash Function, hash tables achieve average $O(1)$ constant-time insertion, deletion, and lookup.
1. Real-World Analogy: The Coat Check / Valet Parking
Imagine parking your car with a luxury hotel valet:
- You don't search all 5,000 cars in the garage when you return.
- You hand the valet your unique numbered ticket (
Ticket #342). - The ticket number points directly to Locker
342where your car keys are hanging! - The Hash Function is the valet who maps your license plate to ticket number
342.
2. Anatomy of a Hash Table
- 1Key: The identifier you want to store (e.g.
'username'). - 2Hash Function: A deterministic algorithm that converts the key into a large integer (hash code), which is then mapped to an array bucket via
hash(key) % table_size. - 3Bucket Array: The internal array where key-value pairs are stored.
3. The Collision Problem & Resolution Strategies
By the Pigeonhole Principle, because there are infinitely more possible string keys than available array buckets, two different keys will eventually hash to the exact same bucket index. This is called a Collision.
Strategy 1: Separate Chaining (Linked Lists / Trees)
Each bucket in the array holds a linked list (or balanced red-black tree in Java 8+). When a collision occurs, the new key-value pair is appended to that bucket's linked list:
Strategy 2: Open Addressing (Linear Probing)
All entries are stored directly in the bucket array itself. If bucket[index] is already occupied:
- Linear Probing: Step forward sequentially: check
index + 1,index + 2,index + 3until an empty cell is found. - Quadratic Probing: Jump by squares: $i + 1^2, i + 2^2, i + 3^2 \dots$
- Double Hashing: Use a secondary hash function to calculate jump intervals.
4. Multi-Language Implementations: Custom Hash Map with Separate Chaining
Python 3 Implementation:
Visual Architecture & Process Flow
How data and code flow step-by-step
Modern JavaScript / TypeScript:
5. Load Factor & Dynamic Resizing
The Load Factor ($\alpha$) measures how full the hash table is: $$\alpha = \frac{\text{Number of Stored Entries } (n)}{\text{Total Number of Buckets } (k)}$$
- When $\alpha > 0.75$, the probability of collisions skyrockets.
- Hash tables automatically rehash and double their bucket capacity, redistributing all elements into the new larger array to maintain average $O(1)$ constant time.
Multiple Choice Questions
Hash Map Patterns: Two Sum, Frequency Counters & Subarray Sums
Continue learning with hands-on practice, examples, and exercises in the upcoming topic.
Related Lessons
Practice Quiz
Test your understanding of this lesson with 5 questions. Each question has one correct answer.