class HashTableDoubleHashing:
def __init__(self, size=11):
self.size = size
self.table = [None] * self.size
self.count = 0
# Primary hash function
def hash(self, key):
return hash(key) % self.size
# Secondary hash function (used for double hashing)
def secondary_hash(self, key):
return 7 - (hash(key) % 7) # A prime number for secondary hash
# Insert using Double Hashing
def insert(self, key, value):
if self.count / self.size >= 0.7:
self._resize()
idx = self.hash(key)
step = self.secondary_hash(key)
original_idx = idx
while self.table[idx] is not None:
if self.table[idx][0] == key:
self.table[idx] = (key, value)
return
idx = (idx + step) % self.size
if idx == original_idx:
raise Exception("Hash table is full!")
self.table[idx] = (key, value)
self.count += 1
# Get value using Double Hashing
def get(self, key):
idx = self.hash(key)
step = self.secondary_hash(key)
original_idx = idx
while self.table[idx] is not None:
if self.table[idx][0] == key:
return self.table[idx][1]
idx = (idx + step) % self.size
if idx == original_idx:
break
return None
# Remove a key-value pair using Double Hashing
def remove(self, key):
idx = self.hash(key)
step = self.secondary_hash(key)
original_idx = idx
while self.table[idx] is not None:
if self.table[idx][0] == key:
self.table[idx] = None
self.count -= 1
self._rehash_after_removal(idx)
return True
idx = (idx + step) % self.size
if idx == original_idx:
break
return False
# Resize the table when load factor exceeds threshold
def _resize(self):
new_size = self._next_prime(self.size * 2)
new_table = [None] * new_size
old_table = self.table
self.table = new_table
self.size = new_size
self.count = 0
for item in old_table:
if item is not None:
key, value = item
self.insert(key, value)
# Helper functions for resizing
def _rehash_after_removal(self, idx):
next_idx = (idx + 1) % self.size
while self.table[next_idx] is not None:
key, value = self.table[next_idx]
self.table[next_idx] = None
self.count -= 1
self.insert(key, value) # Rehash the removed items
next_idx = (next_idx + 1) % self.size
def _next_prime(self, n):
while not self._is_prime(n):
n += 1
return n
def _is_prime(self, num):
if num < 2:
return False
for i in range(2, int(num ** 0.5) + 1):
if num % i == 0:
return False
return True
# Example Usage (Double Hashing)
ht_double = HashTableDoubleHashing()
ht_double.insert("apple", 10)
ht_double.insert("banana", 20)
print(ht_double.get("apple")) # Output: 10
print(ht_double.get("banana")) # Output: 20
ht_double.remove("apple")
print(ht_double.get("apple")) # Output: None