Skip to content

hash functions added #274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 21, 2018
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .hash_table import HashTable

class QuadraticProbing(HashTable):

def __init__(self):
super(self.__class__, self).__init__()
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
Original file line number Diff line number Diff line change
@@ -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