hash functions added by gabrielangelo · Pull Request #274 · TheAlgorithms/Python · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions data_structures/hashing/__init__.py
33 changes: 33 additions & 0 deletions data_structures/hashing/double_hash.py
Original file line number Diff line number Diff line change
@@ -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 changes: 84 additions & 0 deletions data_structures/hashing/hash_table.py
Original file line number Diff line number Diff line change
@@ -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 changes: 24 additions & 0 deletions data_structures/hashing/hash_table_with_linked_list.py
Original file line number Diff line number Diff line change
@@ -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)


Empty file.
29 changes: 29 additions & 0 deletions data_structures/hashing/number_theory/prime_numbers.py
Original file line number Diff line number Diff line change
@@ -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 changes: 26 additions & 0 deletions data_structures/hashing/quadratic_probing.py