Skip to content

Commit 22427fb

Browse files
committed
committed from zkp
1 parent a7d6ea6 commit 22427fb

1 file changed

Lines changed: 156 additions & 0 deletions

File tree

Introduction to algorithms/Dict.py

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# -*- coding: utf-8 -*-
2+
class Array(object):
3+
4+
def __init__(self, size=16, init=None):
5+
self.size = size
6+
self._items = [init] * size
7+
8+
def __len__(self):
9+
return self.size
10+
11+
def __setitem__(self, index, value):
12+
self._items[index] = value
13+
14+
def __getitem__(self, index):
15+
return self._items[index]
16+
17+
def __iter__(self):
18+
for item in self._items:
19+
yield item
20+
21+
def clear(self, init=None):
22+
for i in len(self):
23+
self._items[i] = init
24+
25+
26+
class Slot(object):
27+
28+
def __init__(self, key, value):
29+
self.key, self.value = key, value
30+
31+
32+
class HashTable(object):
33+
UNUSED = None
34+
EMPTY = Slot(None, None)
35+
36+
def __init__(self):
37+
self._table = Array(8, HashTable.UNUSED)
38+
self.length = 0
39+
40+
def __len__(self):
41+
return self.length
42+
43+
@property
44+
def _loadfactor(self):
45+
return self.length / float(len(self._table))
46+
47+
def _hash(self, key):
48+
return abs(hash(key)) % len(self._table)
49+
50+
def slot_can_insert(self, index):
51+
return self._table[index] is HashTable.UNUSED or self._table[index] is HashTable.EMPTY
52+
53+
def find_slot_for_insert(self, key):
54+
index = self._hash(key)
55+
_len = len(self._table)
56+
while not self.slot_can_insert(index):
57+
index = (index * 5 + 1) % _len
58+
return index
59+
60+
def find_key(self, key):
61+
index = self._hash(key)
62+
_len = len(self._table)
63+
while self._table[index] is not HashTable.UNUSED:
64+
if self._table[index] is not HashTable.EMPTY and self._table[index].key == key:
65+
return index
66+
index = (index * 5 + 1) % _len
67+
return None
68+
69+
def __contains__(self, key):
70+
return self.find_key(key) is not None
71+
72+
def add(self, key, value):
73+
if key in self:
74+
index = self.find_key(key)
75+
self._table[index].value = value
76+
return False
77+
else:
78+
index = self.find_slot_for_insert(key)
79+
self._table[index] = Slot(key, value)
80+
self.length += 1
81+
if self._loadfactor >= 0.8:
82+
self._rehash()
83+
return True
84+
85+
def _rehash(self):
86+
old_table = self._table
87+
new_size = len(self._table) * 2
88+
self._table = Array(new_size, HashTable.UNUSED)
89+
self.length = 0
90+
for slot in old_table:
91+
if slot is not HashTable.UNUSED and slot is not HashTable.EMPTY:
92+
key = slot.key
93+
index = self.find_slot_for_insert(key)
94+
self._table[index] = slot
95+
self.length += 1
96+
97+
def get(self, key, default=None):
98+
index = self.find_key(key)
99+
if index is not None:
100+
return self._table[index].value
101+
else:
102+
return default
103+
104+
def remove(self, key):
105+
index = self.find_key(key)
106+
if index is None:
107+
raise KeyError()
108+
value = self._table[index].value
109+
self._table[index] = HashTable.EMPTY
110+
self.length -= 1
111+
return value
112+
113+
def __iter__(self):
114+
for slot in self._table:
115+
if slot is not HashTable.UNUSED and slot is not HashTable.EMPTY:
116+
yield slot.key
117+
118+
119+
class Dict(HashTable):
120+
def _iter_slot(self):
121+
for slot in self._table:
122+
if slot is not HashTable.UNUSED and slot is not HashTable.EMPTY:
123+
yield slot
124+
125+
def __setitem__(self, key, value):
126+
self.add(key, value)
127+
128+
def __getitem__(self, key):
129+
if key not in self:
130+
raise KeyError()
131+
else:
132+
return self.get(key)
133+
134+
def items(self):
135+
for slot in self._iter_slot():
136+
yield(slot.key, slot.value)
137+
138+
def keys(self):
139+
for slot in self._iter_slot():
140+
yield slot.key
141+
142+
def values(self):
143+
for slot in self._iter_slot():
144+
yield slot.value
145+
146+
def test_dict():
147+
d = Dict()
148+
d['a'] = 0
149+
d['b'] = 1
150+
d['c'] = 2
151+
assert d['a'] == 0
152+
assert sorted(list(d.keys())) == ['a', 'b', 'c']
153+
assert sorted(list(d.values())) == [0,1,2]
154+
155+
if __name__ == "__main__":
156+
test_dict()

0 commit comments

Comments
 (0)