0
0
DSA Pythonprogramming

Collision Handling Using Open Addressing Linear Probing in DSA Python

Choose your learning style9 modes available
Mental Model
When two items want the same spot in a table, we look for the next empty spot in order until we find one.
Analogy: Imagine parking cars in a row of parking spots. If your favorite spot is taken, you move forward one spot at a time until you find an empty one to park.
Index: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
Table: [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ]
Dry Run Walkthrough
Input: Insert keys 10, 20, 30 into a hash table of size 10 using linear probing. Hash function: key % 10.
Goal: Insert all keys without overwriting existing keys by finding the next free spot when collision happens.
Step 1: Insert key 10 at index 0 (10 % 10 = 0).
Index: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
Table: [10] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ]
Why: Index 0 is free, so we place 10 there.
Step 2: Insert key 20 at index 0 (20 % 10 = 0), but index 0 is occupied, so move to index 1.
Index: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
Table: [10] -> [20] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ]
Why: Index 0 is taken, so linear probing moves to next index 1 which is free.
Step 3: Insert key 30 at index 0 (30 % 10 = 0), indexes 0 and 1 are occupied, so move to index 2.
Index: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
Table: [10] -> [20] -> [30] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ]
Why: Indexes 0 and 1 are taken, so linear probing moves to next free index 2.
Result:
Index: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
Table: [10] -> [20] -> [30] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ] -> [ ]
Annotated Code
DSA Python
class LinearProbingHashTable:
    def __init__(self, size=10):
        self.size = size
        self.table = [None] * size

    def hash_function(self, key):
        return key % self.size

    def insert(self, key):
        index = self.hash_function(key)
        start_index = index
        while self.table[index] is not None:
            index = (index + 1) % self.size  # move to next index
            if index == start_index:  # table full
                raise Exception("Hash table is full")
        self.table[index] = key

    def __str__(self):
        result = []
        for i, val in enumerate(self.table):
            if val is None:
                result.append(f"[{i}]: Empty")
            else:
                result.append(f"[{i}]: {val}")
        return ' -> '.join(result)

# Driver code
hash_table = LinearProbingHashTable()
hash_table.insert(10)
hash_table.insert(20)
hash_table.insert(30)
print(hash_table)
index = self.hash_function(key)
Calculate initial index using hash function
while self.table[index] is not None:
Check if current index is occupied to handle collision
index = (index + 1) % self.size # move to next index
Move to next index using linear probing
if index == start_index: # table full
Detect full table to avoid infinite loop
self.table[index] = key
Insert key at found free index
OutputSuccess
[0]: 10 -> [1]: 20 -> [2]: 30 -> [3]: Empty -> [4]: Empty -> [5]: Empty -> [6]: Empty -> [7]: Empty -> [8]: Empty -> [9]: Empty
Complexity Analysis
Time: O(n) in worst case because we may check every slot if many collisions happen.
Space: O(n) because we store up to n keys in the table array.
vs Alternative: Compared to chaining (linked lists), linear probing uses less memory but can have clustering causing slower searches.
Edge Cases
Inserting into a full table
Raises an exception to indicate no free slot is available.
DSA Python
if index == start_index:  # table full
Inserting a key when table is empty
Key is inserted directly at hashed index without probing.
DSA Python
while self.table[index] is not None:
Inserting keys that hash to the same index
Linear probing finds next free slot to avoid overwriting existing keys.
DSA Python
index = (index + 1) % self.size  # move to next index
When to Use This Pattern
When you see a hash table with collisions and need to store all keys in one array, use linear probing to find the next free slot by checking sequentially.
Common Mistakes
Mistake: Not wrapping around the table when reaching the end during probing.
Fix: Use modulo operation to wrap index back to start: index = (index + 1) % size.
Mistake: Not checking for full table and causing infinite loop.
Fix: Keep track of start index and stop probing if we return to it.
Summary
It handles collisions by moving forward to find the next empty slot in the hash table.
Use it when you want to store keys in a fixed-size array and handle collisions without extra memory.
The key insight is to keep checking the next slot until you find an empty one, wrapping around the table if needed.