1+ class Array (object ):
2+ def __init__ (self , size = 30 , init = None ):
3+ self .size = size
4+ self .items = [init ]* size
5+ def __getitem__ (self , index ):
6+ return self .items [index ]
7+ def __setitem__ (self , index , value ):
8+ self .items [index ] = value
9+ def __len__ (self ):
10+ return self .size
11+ def clear (self ):
12+ for i in range (len (self .size )):
13+ self .items [i ] = init
14+ def __iter__ (self ):
15+ for i in self .items :
16+ yield i
17+ class Slot (object ):
18+ def __init__ (self , value = None , key = None ):
19+ self .key , self .value = key , value
20+ class HashTable (object ):
21+ EMPTY = None
22+ UNUSED = None
23+ def __init__ (self ):
24+ self ._table = Array (20 , HashTable .UNUSED )
25+ self .length = 0
26+ @property
27+ def _load_factor (self ):
28+ return self .length / len (self ._table )
29+ def __len__ (self ):
30+ return self .length
31+ def _hash (self , key ):
32+ return abs (hash (key )% len (self ._table ))
33+ def _find_key (self , key ):
34+ index = self ._hash (key )
35+ _len = self .length
36+ while self ._table [index ] is not HashTable .UNUSED :
37+ if self ._table [index ] is HashTable .EMPTY :
38+ index = (index * 5 + 1 ) % _len
39+ continue
40+ elif self ._table [index ].key == key :
41+ return index
42+ else :
43+ index = (index * 5 + 1 ) / _len
44+ return None
45+ def _slot_can_insert (self , index ):
46+ return (self ._table [index ] is HashTable .EMPTY or HashTable .UNUSED )
47+ def _find_slots_for_insert (self , key ):
48+ index = self ._hash (key )
49+ _len = self .length
50+ while not _slot_can_insert (index ):
51+ index = (index * 5 + 1 )% _len
52+ return index
53+ def __contains__ (self , key ):
54+ index = _find_key (key )
55+ return index is not None
56+ def add (self , key , value ):
57+ if key in self :
58+ index = self ._find_key (key )
59+ self ._table [index ].value = value
60+ return False
61+ else :
62+ index = _find_slots_for_insert (key )
63+ self ._table [index ] = Slot (value , key )
64+ self .length += 1
65+ if self ._load_factor () >= 0.8 :
66+ self ._rehash ()
67+ return True
68+ def rehash (self ):
69+ old_table = self ._table
70+ newsize = len (self ) * 2
71+ self ._table = Array (newsize , HashTable .UNUSED )
72+ self .length = 0
73+ for slot in old_table :
74+ if slot is not HashTable .UNUSED and slot is not HashTable .EMPTY :
75+ index = self ._find_slots_for_insert (slot .key )
76+ self ._table [index ] = slot
77+ self .length += 1
78+ def get (self , key , default = None ):
79+ index = self ._find_key (key )
80+ if index is None :
81+ return default
82+ else :
83+ return self ._table [index ].value
84+ def remove (self , key ):
85+ index = self ._find_key (key )
86+ if index is None :
87+ raise KeyError ()
88+ value = self ._table [index ].value
89+ self ._table [index ].key = HashTable .EMPTY
90+ self .length -= 1
91+ return value
92+ def __iter__ (self ):
93+ for slot in self ._table :
94+ if slot not in (HashTable .EMPTY , HashTable .UNUSED ):
95+ yield slot .key
0 commit comments