Skip to content

Commit fc3bdb6

Browse files
authoredMar 21, 2018
Merge pull request TheAlgorithms#274 from gabrielangelo/master
hash functions added
2 parents 6b60a6b + 1fa23f5 commit fc3bdb6

File tree

7 files changed

+202
-0
lines changed

7 files changed

+202
-0
lines changed
 

‎data_structures/hashing/__init__.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from .hash_table import HashTable
2+
3+
class QuadraticProbing(HashTable):
4+
5+
def __init__(self):
6+
super(self.__class__, self).__init__()
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env python3
2+
3+
from .hash_table import HashTable
4+
from number_theory.prime_numbers import next_prime, check_prime
5+
6+
7+
class DoubleHash(HashTable):
8+
"""
9+
Hash Table example with open addressing and Double Hash
10+
"""
11+
def __init__(self, *args, **kwargs):
12+
super().__init__(*args, **kwargs)
13+
14+
def __hash_function_2(self, value, data):
15+
16+
next_prime_gt = next_prime(value % self.size_table) \
17+
if not check_prime(value % self.size_table) else value % self.size_table #gt = bigger than
18+
return next_prime_gt - (data % next_prime_gt)
19+
20+
def __hash_double_function(self, key, data, increment):
21+
return (increment * self.__hash_function_2(key, data)) % self.size_table
22+
23+
def _colision_resolution(self, key, data=None):
24+
i = 1
25+
new_key = self.hash_function(data)
26+
27+
while self.values[new_key] is not None and self.values[new_key] != key:
28+
new_key = self.__hash_double_function(key, data, i) if \
29+
self.balanced_factor() >= self.lim_charge else None
30+
if new_key is None: break
31+
else: i += 1
32+
33+
return new_key

‎data_structures/hashing/hash_table.py

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!/usr/bin/env python3
2+
from number_theory.prime_numbers import next_prime
3+
4+
5+
class HashTable:
6+
"""
7+
Basic Hash Table example with open addressing and linear probing
8+
"""
9+
10+
def __init__(self, size_table, charge_factor=None, lim_charge=None):
11+
self.size_table = size_table
12+
self.values = [None] * self.size_table
13+
self.lim_charge = 0.75 if lim_charge is None else lim_charge
14+
self.charge_factor = 1 if charge_factor is None else charge_factor
15+
self.__aux_list = []
16+
self._keys = {}
17+
18+
def keys(self):
19+
return self._keys
20+
21+
def balanced_factor(self):
22+
return sum([1 for slot in self.values
23+
if slot is not None]) / (self.size_table * self.charge_factor)
24+
25+
def hash_function(self, key):
26+
return key % self.size_table
27+
28+
def _step_by_step(self, step_ord):
29+
30+
print("step {0}".format(step_ord))
31+
print([i for i in range(len(self.values))])
32+
print(self.values)
33+
34+
def bulk_insert(self, values):
35+
i = 1
36+
self.__aux_list = values
37+
for value in values:
38+
self.insert_data(value)
39+
self._step_by_step(i)
40+
i += 1
41+
42+
def _set_value(self, key, data):
43+
self.values[key] = data
44+
self._keys[key] = data
45+
46+
def _colision_resolution(self, key, data=None):
47+
new_key = self.hash_function(key + 1)
48+
49+
while self.values[new_key] is not None \
50+
and self.values[new_key] != key:
51+
52+
if self.values.count(None) > 0:
53+
new_key = self.hash_function(new_key + 1)
54+
else:
55+
new_key = None
56+
break
57+
58+
return new_key
59+
60+
def rehashing(self):
61+
survivor_values = [value for value in self.values if value is not None]
62+
self.size_table = next_prime(self.size_table, factor=2)
63+
self._keys.clear()
64+
self.values = [None] * self.size_table #hell's pointers D: don't DRY ;/
65+
map(self.insert_data, survivor_values)
66+
67+
def insert_data(self, data):
68+
key = self.hash_function(data)
69+
70+
if self.values[key] is None:
71+
self._set_value(key, data)
72+
73+
elif self.values[key] == data:
74+
pass
75+
76+
else:
77+
colision_resolution = self._colision_resolution(key, data)
78+
if colision_resolution is not None:
79+
self._set_value(colision_resolution, data)
80+
else:
81+
self.rehashing()
82+
self.insert_data(data)
83+
84+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from .hash_table import HashTable
2+
from collections import deque
3+
4+
5+
class HashTableWithLinkedList(HashTable):
6+
def __init__(self, *args, **kwargs):
7+
super().__init__(*args, **kwargs)
8+
9+
def _set_value(self, key, data):
10+
self.values[key] = deque([]) if self.values[key] is None else self.values[key]
11+
self.values[key].appendleft(data)
12+
self._keys[key] = self.values[key]
13+
14+
def balanced_factor(self):
15+
return sum([self.charge_factor - len(slot) for slot in self.values])\
16+
/ self.size_table * self.charge_factor
17+
18+
def _colision_resolution(self, key, data=None):
19+
if not (len(self.values[key]) == self.charge_factor
20+
and self.values.count(None) == 0):
21+
return key
22+
return super()._colision_resolution(key, data)
23+
24+

‎data_structures/hashing/number_theory/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env python3
2+
"""
3+
module to operations with prime numbers
4+
"""
5+
6+
7+
def check_prime(number):
8+
"""
9+
it's not the best solution
10+
"""
11+
special_non_primes = [0,1,2]
12+
if number in special_non_primes[:2]:
13+
return 2
14+
elif number == special_non_primes[-1]:
15+
return 3
16+
17+
return all([number % i for i in range(2, number)])
18+
19+
20+
def next_prime(value, factor=1, **kwargs):
21+
value = factor * value
22+
first_value_val = value
23+
24+
while not check_prime(value):
25+
value += 1 if not ("desc" in kwargs.keys() and kwargs["desc"] is True) else -1
26+
27+
if value == first_value_val:
28+
return next_prime(value + 1, **kwargs)
29+
return value
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env python3
2+
3+
from .hash_table import HashTable
4+
5+
6+
class QuadraticProbing(HashTable):
7+
"""
8+
Basic Hash Table example with open addressing using Quadratic Probing
9+
"""
10+
def __init__(self, *args, **kwargs):
11+
super().__init__(*args, **kwargs)
12+
13+
def _colision_resolution(self, key, data=None):
14+
i = 1
15+
new_key = self.hash_function(key + i*i)
16+
17+
while self.values[new_key] is not None \
18+
and self.values[new_key] != key:
19+
i += 1
20+
new_key = self.hash_function(key + i*i) if not \
21+
self.balanced_factor() >= self.lim_charge else None
22+
23+
if new_key is None:
24+
break
25+
26+
return new_key

0 commit comments

Comments
 (0)
Please sign in to comment.