Adds _HashMapItem object that will be used to properly handle collisions.

Also adds documentation to the first HM implementation
This commit is contained in:
julien lengrand-lambert
2013-11-26 18:55:16 +01:00
parent ee382ac0a8
commit c51ba44a98

View File

@@ -7,12 +7,27 @@ Collisions are not handled in this version.
2013/11 2013/11
""" """
class _HashMapItem():
"""
Hashmap items are the objects that will be contained in my Hashmaps.
They permit to find the correct value back, even in case of collision.
Not all of my HashMap implementations use HMItems.
"""
def __init__(self, key, value):
self.k = key
self.v = value
class HashMap(): class HashMap():
"""
This implementation does NOT use _HashMapItems
Also, this implementation will return an error in case of a collision.
Data will not be lost, but another key will have to be used.
"""
def __init__(self, hash_size=513): def __init__(self, hash_size=513):
self._hash_size = hash_size self._hash_size = hash_size
self._size = 0 self._size = 0
self.hmap = [None] * self._hash_size self.hmap = [None] * self._hash_size
def add(self, key, value): def add(self, key, value):
""" """
Adds the provided value to the hashmap. Adds the provided value to the hashmap.
@@ -22,96 +37,96 @@ class HashMap():
if self.hmap[my_key] == None: if self.hmap[my_key] == None:
self.hmap[my_key] = value self.hmap[my_key] = value
self._size += 1 self._size += 1
else: else:
raise Exception("Collision detected at index %d", key) raise Exception("Collision detected at index %d", key)
def get(self, key): def get(self, key):
""" """
Finds the element in the hash table that may contain the id for Finds the element in the hash table that may contain the id for
the string we are looking for the string we are looking for
""" """
my_key = self._hash(key) my_key = self._hash(key)
return self.hmap[my_key] return self.hmap[my_key]
def size(self): def size(self):
return self._size return self._size
def _hash(self, value): def _hash(self, value):
""" """
Generates a hash for the given value. Generates a hash for the given value.
The input is expected to be a String, with only ASCII characters. The input is expected to be a String, with only ASCII characters.
# hash function taken from HT3. # hash function taken from HT3.
# We shift and add : << 4 is a *16 # We shift and add : << 4 is a *16
""" """
if len(value) < 1: if len(value) < 1:
raise Exception("Size of value must be greater than one") raise Exception("Size of value must be greater than one")
h = 0 h = 0
for letter in value: for letter in value:
h = (h << 4) + ord(letter) h = (h << 4) + ord(letter)
return h % self._hash_size return h % self._hash_size
class HMTableCollision(HashMap): class HMTableCollision(HashMap):
""" """
Extension of the previous HashMap implementation that takes care of Extension of the previous HashMap implementation that takes care of
collisions. collisions.
Instead of having only one slot available per index in the table, Instead of having only one slot available per index in the table,
each index will contain a list. This means several elements can be each index will contain a list. This means several elements can be
stored with the same index. stored with the same index.
""" """
def __init__(self, hash_size=513): def __init__(self, hash_size=513):
self._hash_size = hash_size self._hash_size = hash_size
self._size = 0 self._size = 0
self.hmap = [None] * self._hash_size self.hmap = [None] * self._hash_size
def add(self, key, value): def add(self, key, value):
""" """
Adds the provided value to the hashmap. Adds the provided value to the hashmap.
Raises an Exception if a collision is detected Raises an Exception if a collision is detected
""" """
my_key = self._hash(key) my_key = self._hash(key)
if self.hmap[my_key] == None: if self.hmap[my_key] == None:
self.hmap[my_key] = [value] self.hmap[my_key] = [value]
else: else:
self.hmap[my_key].append(value) self.hmap[my_key].append(value)
self._size += 1 self._size += 1
def get(self, key): def get(self, key):
""" """
Finds the element in the hash table that may contain the id for Finds the element in the hash table that may contain the id for
the string we are looking for the string we are looking for
""" """
my_key = self._hash(key) my_key = self._hash(key)
vals = self.hmap[my_key] vals = self.hmap[my_key]
if vals is None: if vals is None:
return vals return vals
elif len(vals) == 1: elif len(vals) == 1:
return vals[0] return vals[0]
else: else:
return vals # we return all the results if there are several return vals # we return all the results if there are several
def size(self): def size(self):
return self._size return self._size
def _hash(self, value): def _hash(self, value):
""" """
Generates a hash for the given value. Generates a hash for the given value.
The input is expected to be a String, with only ASCII characters. The input is expected to be a String, with only ASCII characters.
# hash function taken from HT3. # hash function taken from HT3.
# We shift and add : << 4 is a *16 # We shift and add : << 4 is a *16
""" """
if len(value) < 1: if len(value) < 1:
raise Exception("Size of value must be greater than one") raise Exception("Size of value must be greater than one")
h = 0 h = 0
for letter in value: for letter in value:
h = (h << 4) + ord(letter) h = (h << 4) + ord(letter)
return h % self._hash_size return h % self._hash_size
class HMNeighbourCollision(): class HMNeighbourCollision():
@@ -119,7 +134,7 @@ class HMNeighbourCollision():
self._hash_size = hash_size self._hash_size = hash_size
self._size = 0 self._size = 0
self.hmap = [None] * self._hash_size self.hmap = [None] * self._hash_size
def add(self, key, value): def add(self, key, value):
""" """
Adds the provided value to the hashmap. Adds the provided value to the hashmap.
@@ -127,7 +142,7 @@ class HMNeighbourCollision():
""" """
my_key = self._hash(key) my_key = self._hash(key)
idx = self._find_free_idx(my_key) idx = self._find_free_idx(my_key)
self.hmap[idx] = value self.hmap[idx] = value
self._size += 1 self._size += 1
@@ -139,7 +154,7 @@ class HMNeighbourCollision():
idx = key idx = key
cur_ptr = 1 cur_ptr = 1
negative = True negative = True
while(True): while(True):
if self.hmap[idx] == None: if self.hmap[idx] == None:
return idx return idx
@@ -151,30 +166,30 @@ class HMNeighbourCollision():
idx = key + cur_ptr idx = key + cur_ptr
negative = True negative = True
cur_ptr += 1 cur_ptr += 1
def get(self, key): def get(self, key):
""" """
Finds the element in the hash table that may contain the id for Finds the element in the hash table that may contain the id for
the string we are looking for the string we are looking for
""" """
#TODO #TODO
def size(self): def size(self):
return self._size return self._size
def _hash(self, value): def _hash(self, value):
""" """
Generates a hash for the given value. Generates a hash for the given value.
The input is expected to be a String, with only ASCII characters. The input is expected to be a String, with only ASCII characters.
# hash function taken from HT3. # hash function taken from HT3.
# We shift and add : << 4 is a *16 # We shift and add : << 4 is a *16
""" """
if len(value) < 1: if len(value) < 1:
raise Exception("Size of value must be greater than one") raise Exception("Size of value must be greater than one")
h = 0 h = 0
for letter in value: for letter in value:
h = (h << 4) + ord(letter) h = (h << 4) + ord(letter)
return h % self._hash_size return h % self._hash_size