Обновить u7/hash_table.py
This commit is contained in:
parent
7f9d5036d8
commit
2dc1599774
104
u7/hash_table.py
104
u7/hash_table.py
@ -0,0 +1,104 @@
|
||||
class HashTable:
|
||||
_DELETED = object()
|
||||
def __init__(self, capacity=10):
|
||||
if type(capacity) != int:
|
||||
raise TypeError("Capacity must be an integer")
|
||||
if capacity <= 0:
|
||||
raise ValueError("Capacity must be positive")
|
||||
self._capacity = capacity
|
||||
self._table = [None] * capacity
|
||||
self._size = 0
|
||||
@property
|
||||
def capacity(self):
|
||||
return self._capacity
|
||||
def hash(self, key):
|
||||
if type(key) != str:
|
||||
raise TypeError
|
||||
h = 0
|
||||
for char in key:
|
||||
h = (31 * h + ord(char)) % self.capacity
|
||||
return h
|
||||
def probe(self, key):
|
||||
if type(key) != str:
|
||||
raise TypeError
|
||||
start = self.hash(key)
|
||||
deleted = None
|
||||
for i in range(self.capacity):
|
||||
index = (start + i) % self.capacity
|
||||
item = self._table[index]
|
||||
if item is None:
|
||||
if deleted is not None:
|
||||
return deleted
|
||||
return index
|
||||
if item is self._DELETED:
|
||||
if deleted is None:
|
||||
deleted = index
|
||||
elif item[0] == key:
|
||||
return index
|
||||
if deleted is not None:
|
||||
return deleted
|
||||
raise RuntimeError
|
||||
def __setitem__(self, key, value):
|
||||
if type(key) != str:
|
||||
raise TypeError
|
||||
try:
|
||||
index = self.probe(key)
|
||||
item = self._table[index]
|
||||
if item is not None and item is not self._DELETED:
|
||||
if item[0] == key:
|
||||
self._table[index] = (key, value)
|
||||
return
|
||||
except RuntimeError:
|
||||
pass
|
||||
if (self._size + 1) / self.capacity > 0.7:
|
||||
old_table = self._table
|
||||
self._capacity = self._capacity * 2
|
||||
self._table = [None] * self.capacity
|
||||
self._size = 0
|
||||
for item in old_table:
|
||||
if item is not None and item is not self._DELETED:
|
||||
index = self.probe(item[0])
|
||||
self._table[index] = item
|
||||
self._size += 1
|
||||
index = self.probe(key)
|
||||
self._table[index] = (key, value)
|
||||
self._size += 1
|
||||
def __getitem__(self, key):
|
||||
if type(key) != str:
|
||||
raise TypeError
|
||||
index = self.probe(key)
|
||||
item = self._table[index]
|
||||
if item is None or item is self._DELETED:
|
||||
raise KeyError(key)
|
||||
return item[1]
|
||||
def __delitem__(self, key):
|
||||
if type(key) != str:
|
||||
raise TypeError
|
||||
index = self.probe(key)
|
||||
item = self._table[index]
|
||||
if item is None or item is self._DELETED:
|
||||
raise KeyError(key)
|
||||
self._table[index] = self._DELETED
|
||||
self._size -= 1
|
||||
def __contains__(self, key):
|
||||
if type(key) != str:
|
||||
raise TypeError
|
||||
try:
|
||||
index = self.probe(key)
|
||||
item = self._table[index]
|
||||
if item is not None and item is not self._DELETED:
|
||||
if item[0] == key:
|
||||
return True
|
||||
return False
|
||||
except RuntimeError:
|
||||
return False
|
||||
def __len__(self):
|
||||
return self._size
|
||||
def __iter__(self):
|
||||
keys = []
|
||||
for item in self._table:
|
||||
if item is not None and item is not self._DELETED:
|
||||
keys.append(item[0])
|
||||
return iter(keys)
|
||||
def load_factor(self):
|
||||
return self._size / self.capacity
|
||||
Loading…
Reference in New Issue
Block a user