1+ class Array (object ):
2+ def __init__ (self , size = 32 , init = None ):
3+ self .size = size
4+ self .items = [init ] * size
5+ def clear (self , value = None ):
6+ for i in range (len (self )):
7+ self .items [i ] = value
8+ def __len__ (self ):
9+ return self .size
10+ def __getitem__ (self , index ):
11+ return self .items [index ]
12+ def __setitem__ (self , index , value ):
13+ self .items [index ] = value
14+ def __iter__ (self ):
15+ for item in self .items :
16+ yield item
17+ class Slot (object ):
18+ def __init__ (self , key = None , value = None ):
19+ self .key , self .value = key , value
20+ class HashTable (object ):
21+ UNUSED = None
22+ EMPTY = Slot ()
23+ def __init__ (self ):
24+ self ._table = Array (8 , init = HashTable .UNUSED )
25+ self .length = 0
26+ def __len__ (self ):
27+ return self .length
28+ def _hash (self , key ):
29+ return abs (hash (key )) % len (self ._table )
30+ @property
31+ def load_factor (self ):
32+ return self .length / len (self ._table )
33+ def find_key (self , key ):
34+ index = self ._hash (key )
35+ while self ._table [index ] is not HashTable .UNUSED :
36+ if self ._table [index ] is not HashTable .EMPTY and self ._table [index ].key == key :
37+ return index
38+ index = (index * 5 + 1 )% len (self ._table )
39+ return None
40+ def find_key_to_insert (self , key ):
41+ index = self ._hash (key )
42+ while self ._table [index ] not in (HashTable .UNUSED , HashTable .EMPTY ):
43+ index = (index * 5 + 1 ) % len (self ._table )
44+ return index
45+ def add (self , key , value ):
46+ if self .find_key (key ):
47+ self ._table [index ].value = value
48+ else :
49+ index = self .find_key_to_insert (key )
50+ slot = Slot (key , value )
51+ self ._table [index ] = slot
52+ self .length += 1
53+ if self .load_factor >= 0.8 :
54+ self ._rehash_table ()
55+ def _rehash_table (self ):
56+ old_table = self ._table
57+ newsize = len (self ._table ) * 2
58+ self ._table = Array (newsize , HashTable .UNUSED )
59+ for i in old_table :
60+ if i not in (HashTable .UNUSED , HashTable .EMPTY ):
61+ index = self .find_key_to_insert (i .key )
62+ self ._table [index ] = i
63+ def remove (self , key ):
64+ index = self .find_key (key )
65+ if index is not None :
66+ self ._table [index ] = HashTable .EMPTY
67+ self .length -= 1
68+ else :
69+ raise KeyError ('Not Found' )
70+ def __iter__ (self ):
71+ for item in self ._table :
72+ if item not in (HashTable .UNUSED , HashTable .EMPTY ):
73+ yield (item .key , item .value )
74+ def __contains__ (self , key ):
75+ if self .find_key (key ):
76+ return True
77+ return False
78+ def get (self , key , default = None ):
79+ index = self .find_key (key )
80+ if index is not None :
81+ return self ._table [index ].value
82+ return default
83+ class DictADT (HashTable ):
84+ def __setitem__ (self , key , value ):
85+ self .add (key , value )
86+ def __getitem__ (self , key ):
87+ return self .get (key )
88+ def items (self ):
89+ for item in self :
90+ yield item
91+ def keys (self ):
92+ for item in self :
93+ yield item [0 ]
94+ def values (self ):
95+ for item in self :
96+ yield item [1 ]
97+ def test ():
98+ import random
99+ a = DictADT ()
100+ a .add ('a' , 1 )
101+ assert len (a ) == 1
102+ assert a ['a' ] == 1
103+ a .remove ('a' )
104+ assert len (a ) == 0
105+ l = list (range (30 ))
106+ random .shuffle (l )
107+ for i in l :
108+ a [i ] = i
109+ assert a [i ] == i
110+ assert len (a ) == 30
111+ assert sorted (a .values ()) == sorted (l )
112+ print ('Successful' )
113+ if __name__ == "__main__" :
114+ test ()
0 commit comments