class Array(object):
def __init__(self,size=64,init=None):
self._size = size
self._items = [init] * size
def __getitem__(self,index):
return self._items[index]
def __setitem__(self, index, value):
self._items[index] = value
def __len__(self):
return self._size(self)
def clear(self,value=None):
for i in range(self._items):
self._items[i] = value
def __iter__(self):
for item in self._items:
yield item
class Slot(object):
def __init(self,key,value):
self.key,self,value = key,value
class HashTable(object):
UNUESD = None
EMPTY = None
def __init__(self):
self._table = Array(8,init=HashTable.UNUESD)
self.length = 0
@property
def _load_factor(self):
return self.length / float(len(self._table))
def __len__(self):
return self.length
def __hash(self,key):
return abs(hash(key)) % len(self._table)
def _find_key(self,key):
index = self.__hash(key)
_len = len(self._table)
while self._table[index] is not HashTable.UNUESD:
if self._table[index] is HashTable.EMPTY:
index = (index*5 +1) % _len
continue
elif self._table[index].key == key:
return index
else:
index = (index*5 + 1) %_len
return None
def _slot_can_insert(self,index):
return (self._table[index] is HashTable.EMPTY
or self.table[index] is HashTable.UNUESD)
def _find_slot_for_insert(self,key):
index = self.__hash(key)
_len = len(self._table)
while not self._slot_can_insert(index):
index = (index * 5 + 1) % _len
return index
def __cantains__(self,key):
index = self._find_key(key)
return index is not None
def add(self,key,value):
if key in self:
index = self._find_key(key)
self._table[index].value = value
return False
else:
index = self._find_slot_for_insert(key)
self._table[index] = Slot(key,value)
self.length += 1
if self._load_factor > 0.8:
self._rehash()
return True
def _rehash(self):
old_table = self._table
newsize = len(self._table) *2
self._table = Array(newsize,HashTable.UNUESD)
self.length = 0
if Slot is not HashTable.UNUESD and Slot is not HashTable.EMPTY:
index = self._find_slot_for_insert(Slot.key)