mirror of
https://hub.njuu.cf/TheAlgorithms/Python.git
synced 2023-10-11 13:06:12 +08:00
hash functions added
This commit is contained in:
parent
aa8485b4df
commit
1fa23f57d7
6
data_structures/hashing/__init__.py
Normal file
6
data_structures/hashing/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
from .hash_table import HashTable
|
||||
|
||||
class QuadraticProbing(HashTable):
|
||||
|
||||
def __init__(self):
|
||||
super(self.__class__, self).__init__()
|
33
data_structures/hashing/double_hash.py
Normal file
33
data_structures/hashing/double_hash.py
Normal file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from .hash_table import HashTable
|
||||
from number_theory.prime_numbers import next_prime, check_prime
|
||||
|
||||
|
||||
class DoubleHash(HashTable):
|
||||
"""
|
||||
Hash Table example with open addressing and Double Hash
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def __hash_function_2(self, value, data):
|
||||
|
||||
next_prime_gt = next_prime(value % self.size_table) \
|
||||
if not check_prime(value % self.size_table) else value % self.size_table #gt = bigger than
|
||||
return next_prime_gt - (data % next_prime_gt)
|
||||
|
||||
def __hash_double_function(self, key, data, increment):
|
||||
return (increment * self.__hash_function_2(key, data)) % self.size_table
|
||||
|
||||
def _colision_resolution(self, key, data=None):
|
||||
i = 1
|
||||
new_key = self.hash_function(data)
|
||||
|
||||
while self.values[new_key] is not None and self.values[new_key] != key:
|
||||
new_key = self.__hash_double_function(key, data, i) if \
|
||||
self.balanced_factor() >= self.lim_charge else None
|
||||
if new_key is None: break
|
||||
else: i += 1
|
||||
|
||||
return new_key
|
84
data_structures/hashing/hash_table.py
Normal file
84
data_structures/hashing/hash_table.py
Normal file
@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3
|
||||
from number_theory.prime_numbers import next_prime
|
||||
|
||||
|
||||
class HashTable:
|
||||
"""
|
||||
Basic Hash Table example with open addressing and linear probing
|
||||
"""
|
||||
|
||||
def __init__(self, size_table, charge_factor=None, lim_charge=None):
|
||||
self.size_table = size_table
|
||||
self.values = [None] * self.size_table
|
||||
self.lim_charge = 0.75 if lim_charge is None else lim_charge
|
||||
self.charge_factor = 1 if charge_factor is None else charge_factor
|
||||
self.__aux_list = []
|
||||
self._keys = {}
|
||||
|
||||
def keys(self):
|
||||
return self._keys
|
||||
|
||||
def balanced_factor(self):
|
||||
return sum([1 for slot in self.values
|
||||
if slot is not None]) / (self.size_table * self.charge_factor)
|
||||
|
||||
def hash_function(self, key):
|
||||
return key % self.size_table
|
||||
|
||||
def _step_by_step(self, step_ord):
|
||||
|
||||
print("step {0}".format(step_ord))
|
||||
print([i for i in range(len(self.values))])
|
||||
print(self.values)
|
||||
|
||||
def bulk_insert(self, values):
|
||||
i = 1
|
||||
self.__aux_list = values
|
||||
for value in values:
|
||||
self.insert_data(value)
|
||||
self._step_by_step(i)
|
||||
i += 1
|
||||
|
||||
def _set_value(self, key, data):
|
||||
self.values[key] = data
|
||||
self._keys[key] = data
|
||||
|
||||
def _colision_resolution(self, key, data=None):
|
||||
new_key = self.hash_function(key + 1)
|
||||
|
||||
while self.values[new_key] is not None \
|
||||
and self.values[new_key] != key:
|
||||
|
||||
if self.values.count(None) > 0:
|
||||
new_key = self.hash_function(new_key + 1)
|
||||
else:
|
||||
new_key = None
|
||||
break
|
||||
|
||||
return new_key
|
||||
|
||||
def rehashing(self):
|
||||
survivor_values = [value for value in self.values if value is not None]
|
||||
self.size_table = next_prime(self.size_table, factor=2)
|
||||
self._keys.clear()
|
||||
self.values = [None] * self.size_table #hell's pointers D: don't DRY ;/
|
||||
map(self.insert_data, survivor_values)
|
||||
|
||||
def insert_data(self, data):
|
||||
key = self.hash_function(data)
|
||||
|
||||
if self.values[key] is None:
|
||||
self._set_value(key, data)
|
||||
|
||||
elif self.values[key] == data:
|
||||
pass
|
||||
|
||||
else:
|
||||
colision_resolution = self._colision_resolution(key, data)
|
||||
if colision_resolution is not None:
|
||||
self._set_value(colision_resolution, data)
|
||||
else:
|
||||
self.rehashing()
|
||||
self.insert_data(data)
|
||||
|
||||
|
24
data_structures/hashing/hash_table_with_linked_list.py
Normal file
24
data_structures/hashing/hash_table_with_linked_list.py
Normal file
@ -0,0 +1,24 @@
|
||||
from .hash_table import HashTable
|
||||
from collections import deque
|
||||
|
||||
|
||||
class HashTableWithLinkedList(HashTable):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def _set_value(self, key, data):
|
||||
self.values[key] = deque([]) if self.values[key] is None else self.values[key]
|
||||
self.values[key].appendleft(data)
|
||||
self._keys[key] = self.values[key]
|
||||
|
||||
def balanced_factor(self):
|
||||
return sum([self.charge_factor - len(slot) for slot in self.values])\
|
||||
/ self.size_table * self.charge_factor
|
||||
|
||||
def _colision_resolution(self, key, data=None):
|
||||
if not (len(self.values[key]) == self.charge_factor
|
||||
and self.values.count(None) == 0):
|
||||
return key
|
||||
return super()._colision_resolution(key, data)
|
||||
|
||||
|
0
data_structures/hashing/number_theory/__init__.py
Normal file
0
data_structures/hashing/number_theory/__init__.py
Normal file
29
data_structures/hashing/number_theory/prime_numbers.py
Normal file
29
data_structures/hashing/number_theory/prime_numbers.py
Normal file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
module to operations with prime numbers
|
||||
"""
|
||||
|
||||
|
||||
def check_prime(number):
|
||||
"""
|
||||
it's not the best solution
|
||||
"""
|
||||
special_non_primes = [0,1,2]
|
||||
if number in special_non_primes[:2]:
|
||||
return 2
|
||||
elif number == special_non_primes[-1]:
|
||||
return 3
|
||||
|
||||
return all([number % i for i in range(2, number)])
|
||||
|
||||
|
||||
def next_prime(value, factor=1, **kwargs):
|
||||
value = factor * value
|
||||
first_value_val = value
|
||||
|
||||
while not check_prime(value):
|
||||
value += 1 if not ("desc" in kwargs.keys() and kwargs["desc"] is True) else -1
|
||||
|
||||
if value == first_value_val:
|
||||
return next_prime(value + 1, **kwargs)
|
||||
return value
|
26
data_structures/hashing/quadratic_probing.py
Normal file
26
data_structures/hashing/quadratic_probing.py
Normal file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from .hash_table import HashTable
|
||||
|
||||
|
||||
class QuadraticProbing(HashTable):
|
||||
"""
|
||||
Basic Hash Table example with open addressing using Quadratic Probing
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def _colision_resolution(self, key, data=None):
|
||||
i = 1
|
||||
new_key = self.hash_function(key + i*i)
|
||||
|
||||
while self.values[new_key] is not None \
|
||||
and self.values[new_key] != key:
|
||||
i += 1
|
||||
new_key = self.hash_function(key + i*i) if not \
|
||||
self.balanced_factor() >= self.lim_charge else None
|
||||
|
||||
if new_key is None:
|
||||
break
|
||||
|
||||
return new_key
|
Loading…
Reference in New Issue
Block a user