Open Addressing and Chaining are two popular techniques for handling collisions in hash tables. Collisions occur when two or more keys produce the same hash value, leading them to the same location in the hash table.
Here’s a detailed look at each method:
Open Addressing resolves collisions by finding another open slot within the hash table itself. When a collision happens, the algorithm searches for an empty slot (or address) according to a specific probing method. This means that each element stays within the table array, without using additional data structures like linked lists.
Linear Probing:
Example: index = (hash + i) % tableSize
Quadratic Probing:
(hash + 1^2), (hash + 2^2), etc.Example: index = (hash + i^2) % tableSize
Double Hashing:
Example: index = (hash1(key) + i * hash2(key)) % tableSize
#include <iostream>
#include <vector>
using namespace std;
class HashTable {
vector<int> table;
int tableSize;
public:
HashTable(int size) : table(size, -1), tableSize(size) {} // Initialize table with -1
int hashFunction(int key) {
return key % tableSize;
}
void insert(int key) {
int index = hashFunction(key);
int i = 0;
// Linear probing
while (table[(index + i) % tableSize] != -1) {
i++;
}
table[(index + i) % tableSize] = key;
cout << "Inserted " << key << " at index " << (index + i) % tableSize << endl;
}
void display() {
for (int i = 0; i < tableSize; i++) {
cout << i << ": " << table[i] << endl;
}
}
};
int main() {
HashTable ht(7);
ht.insert(10);
ht.insert(20);
ht.insert(15);
ht.insert(7);
ht.display();
return 0;
}
Chaining resolves collisions by storing all elements that hash to the same index in a linked list (or any other data structure like a dynamic array) at that index. When a collision occurs, the new element is added to the linked list at the hashed index, allowing multiple elements to exist at the same index.
#include <iostream>
#include <list>
#include <vector>
using namespace std;
class HashTable {
vector<list<int>> table; // Each index stores a linked list
int tableSize;
public:
HashTable(int size) : table(size), tableSize(size) {}
int hashFunction(int key) {
return key % tableSize;
}
void insert(int key) {
int index = hashFunction(key);
table[index].push_back(key);
cout << "Inserted " << key << " at index " << index << endl;
}
void display() {
for (int i = 0; i < tableSize; i++) {
cout << i << ": ";
for (int key : table[i]) {
cout << key << " -> ";
}
cout << "nullptr" << endl;
}
}
};
int main() {
HashTable ht(7);
ht.insert(10);
ht.insert(20);
ht.insert(15);
ht.insert(7);
ht.display();
return 0;
}
| Feature | Open Addressing | Chaining |
|---|---|---|
| Structure | Stores all elements within the array | Uses linked lists at each index |
| Memory Usage | Only the hash table size is used | Additional memory needed for linked lists |
| Collision Resolution | Finds alternative slots using probing | Stores collided elements in a linked list |
| Clustering | Subject to clustering | No clustering, as lists are separate |
| Performance | Can degrade with clustering | Performance stable with well-sized lists |
| Table Fullness | Degrades as table nears capacity | Can handle more elements than table size |
In summary:
Open this section to load past papers