Collision Handling Using Open Addressing Linear Probing
📖 Scenario: Imagine you are building a simple phone book app that stores phone numbers by names. Sometimes, two names might want to use the same spot in your storage. To handle this, you will use a method called linear probing to find the next free spot.
🎯 Goal: You will create a small hash table using a vector in Rust. You will insert names and phone numbers. When a spot is taken, you will use linear probing to find the next empty spot. Finally, you will print the state of the hash table.
📋 What You'll Learn
Create a vector to represent the hash table with fixed size
Create a simple hash function to find index from name
Implement linear probing to handle collisions
Insert multiple entries and print the final hash table
💡 Why This Matters
🌍 Real World
Hash tables with collision handling are used in databases, caches, and many software systems to store and retrieve data quickly.
💼 Career
Understanding collision handling and hash tables is essential for software engineers working on performance-critical applications and data storage solutions.
Progress0 / 4 steps
1
Create the hash table vector
Create a vector called hash_table with 5 elements, each initialized to None. Use Option<(String, String)> as the type to store name and phone number pairs.
DSA Rust
Hint
Use vec![None; 5] to create a vector with 5 empty slots.
2
Create a simple hash function
Create a function called hash that takes a &str called key and returns a usize. The function should return the sum of the bytes of key modulo 5.
DSA Rust
Hint
Use key.bytes() to get bytes, sum them, then use % 5 to get index.
3
Insert entries using linear probing
Write a function called insert that takes hash_table: &mut Vec, key: String, and value: String. Use the hash function to find the start index. If the spot is taken, move to the next index (wrap around) until an empty spot is found. Insert the (key, value) pair there.
DSA Rust
Hint
Use a loop and check if hash_table[index] is None. If not, increase index by 1 and wrap around.
4
Insert entries and print the hash table
Insert these entries into hash_table using insert: ("Alice", "123"), ("Bob", "456"), ("Carol", "789"), ("Dave", "101"), ("Eve", "112"). Then print the hash_table showing each index and the stored pair or Empty if none.
DSA Rust
Hint
Call insert for each pair. Then use a for loop with enumerate() to print each index and its content.
Practice
(1/5)
1. What is the main idea behind linear probing in collision handling for hash tables?
easy
A. Use a secondary hash function to find a new slot.
B. Use a linked list to store multiple values at the same index.
C. Double the size of the hash table when a collision happens.
D. If a collision occurs, check the next slot sequentially until an empty slot is found.
Solution
Step 1: Understand collision handling methods
Linear probing is a method where, upon collision, the algorithm checks the next slot in the array sequentially.
Step 2: Compare with other methods
Other methods include chaining (linked lists), resizing, or double hashing, but linear probing specifically uses sequential slots.
Final Answer:
If a collision occurs, check the next slot sequentially until an empty slot is found. -> Option D
Quick Check:
Linear probing = sequential slot check [OK]
Hint: Linear probing means try next slot one by one [OK]
Common Mistakes:
Confusing linear probing with chaining
Thinking linear probing uses a second hash function
Assuming table size doubles on collision
2. Which of the following Rust code snippets correctly implements linear probing to find the next index after a collision in a hash table of size table_size?
easy
A. let next_index = (current_index + 1) % table_size;
B. let next_index = (current_index * 2) % table_size;
C. let next_index = (current_index - 1) % table_size;
D. let next_index = (current_index + 3) % table_size;
Solution
Step 1: Understand linear probing index calculation
Linear probing moves to the next slot by adding 1 to the current index and wrapping around using modulo.
Step 2: Check each option
let next_index = (current_index + 1) % table_size; adds 1 and uses modulo, which is correct. Others multiply or subtract, which are not standard linear probing steps.
Final Answer:
let next_index = (current_index + 1) % table_size; -> Option A
Quick Check:
Linear probing = increment index by 1 modulo table size [OK]
Hint: Linear probing increments index by 1 modulo table size [OK]
Common Mistakes:
Using multiplication instead of addition
Subtracting index without handling negative wrap
Skipping modulo operation causing out-of-bounds
3. Consider the following Rust code snippet for inserting keys into a hash table using linear probing. What will be the final state of the hash table array after inserting keys [5, 15, 25] with table size 10 and hash function key % 10?
let mut table = vec![None; 10];
let keys = vec![5, 15, 25];
for &key in &keys {
let mut index = key % 10;
while table[index].is_some() {
index = (index + 1) % 10;
}
table[index] = Some(key);
}
println!("{:?}", table);
Hint: Keys with same hash go to next free slot sequentially [OK]
Common Mistakes:
Placing all keys at index 5 ignoring collisions
Skipping modulo wrap-around
Inserting keys at wrong indices after collision
4. The following Rust code attempts to insert keys into a hash table using linear probing. However, it sometimes causes an infinite loop. What is the bug?
let mut table = vec![None; 5];
let keys = vec![1, 6, 11];
for &key in &keys {
let mut index = key % 5;
while table[index].is_some() {
index = (index + 1) % 5;
}
table[index] = Some(key);
}
medium
A. The code does not check if the table is full, causing infinite loop when no empty slot exists.
B. The modulo operator is used incorrectly; it should be key % 6.
C. The loop should break after checking only once to avoid infinite loop.
D. The vector size is too large, causing index out of bounds.
Solution
Step 1: Analyze the while loop condition
The loop continues while the slot is occupied, moving to next index with wrap-around.
Step 2: Identify missing termination condition
If the table is full, the loop cycles endlessly because no empty slot is found and no exit condition exists.
Final Answer:
The code does not check if the table is full, causing infinite loop when no empty slot exists. -> Option A
Hint: Always check for full table to avoid infinite loops [OK]
Common Mistakes:
Ignoring full table condition
Changing modulo divisor incorrectly
Breaking loop too early causing wrong insertion
5. You have a hash table of size 7 using linear probing for collision handling. You insert keys [10, 20, 15, 7, 32] with hash function key % 7. After all insertions, what is the state of the table? Represent empty slots as null.
Explain your answer step-by-step.