1+ import MapBase
2+
3+ class SortedTableMap (MapBase ):
4+ """Map implementation using a sorted Table"""
5+
6+ #Protected / Private methods
7+ def _find_index (self , k , low , high ):
8+ """Uses the Binary search algorithm and returns the index of the target key,
9+ if item does not exist return index of item is max key
10+
11+ Return index of the left most item with key greater than or equal to k
12+
13+ return high + 1 if no such item qualifies (item with max key in this case)
14+
15+ That is j will be return such that:
16+ all items of slice table[low: j] have key < k
17+ all items of slice table[j: high+1] have key >= k
18+ """
19+
20+ if high < low :
21+ return high + 1 #if no key qualifies return index of item with max key
22+ else :
23+ #perform binary search
24+ mid = (high + low ) // 2
25+ if k == self ._table [mid ]:
26+ return mid
27+ elif k < self ._table [mid ]:
28+ self ._find_index (k , low , mid - 1 )
29+ else :
30+ self ._find_index (k , mid + 1 , high )
31+
32+ # ---------- Public Methods --------------
33+ def __init__ (self ):
34+ """create an empty map as array based sequence (list)"""
35+ self ._table = []
36+
37+ def __len__ (self ):
38+ """Return number of items in the map"""
39+ return len (self ._table )
40+
41+ def __getitem__ (self , k ):
42+ """Return index of (key,value) where k = key, Raise Error if key not found"""
43+
44+ j = self ._find_index (self ._table , k , 0 , len (self ._table )- 1 ) # perform binary search for look up and store in j
45+
46+ # if index j is the last index of map or no item in map contains the key at a certain index raise error
47+ if j == len (self ._table ) or self ._table [j ]._key != k :
48+ raise KeyError ("Key Error: " + repr (k ))
49+
50+ return self ._table [j ]._value # return value assciated with key k if at index j there is a k == key of item at j
51+
52+ def __setitem__ (self , k , v ):
53+ """Assign value v to key k, overwriting existin value if another value is present at target k"""
54+ j = self ._find_index (k , 0 , len (self ._table )- 1 )
55+
56+ if j < len (self ._table ) and self ._table [j ]._key == k : # index j that has key == to target k must be less than length of map
57+ self ._table [j ]._value = v #swap value if item with key k already has a value
58+ else :
59+ self ._table .insert (j , self ._Item (k ,v )) # Add new item at position j
60+
61+ def __delitem__ (self , k ):
62+ """Remove Item associated with key k (raise error if key not found in map)"""
63+ j = self ._find_index (k , 0 , len (self ._table )- 1 )
64+
65+ if j == len (self ._table ) or self ._table [j ]._key != k : #if no item has key k for any index j or j is last element in map
66+ raise KeyError ("Key Error" + repr (k )) #raise error as key does not exist in map
67+
68+ def __iter__ (self ):
69+ """Generate keys of the mpa ordered from minimum to maximum key"""
70+ for item in self ._table :
71+ yield item ._key
72+
73+ def __reversed__ (self ):
74+ """Generate keys of the map from maximum to minimum"""
75+ for item in reversed (self ._table ):
76+ yield item ._key
77+
78+ def find_min (self ):
79+ """Return the item (k,v) where k is the minimum key in map or None if map is empty"""
80+ if len (self ._table ) > 0 :
81+ return (self ._table [0 ]._key , self ._table [0 ]._value )
82+ else :
83+ None
84+
85+ def find_max (self ):
86+ """Return item (k,v) where k is the maximum key in map or None if map is empty"""
87+ if len (self ._table )> 0 :
88+ return (self ._table [- 1 ]._key , self ._table [- 1 ]._value )
89+ else :
90+ return None
91+
92+ def find_ge (self , k ):
93+ """return (k,v) pair with least key greater than or equal to k"""
94+ j = self ._find_index (k , 0 , len (self ._table )- 1 ) # j's key >= k
95+
96+ if j < len (self ._table ):
97+ return (self ._table [j ]._key , self ._table [j ]._value )
98+ else :
99+ return None
100+
101+ def find_lt (self , k ):
102+ """return (k,v) pair with greatest key strictly smaller than k"""
103+ j = self ._find_index (k , 0 , len (self ._table )- 1 )
104+
105+ if j < len (self ._table ):
106+ return (self ._table [j - 1 ]._key , self ._table [j - 1 ]._value ) # j-1 since is greatest key < than k
107+ else :
108+ return None
109+
110+ def find_gt (self , k ):
111+ """Return (key,value) pair with least key strictly greater than k."""
112+ j = self ._find_index (k , 0 , len (self . table ) - 1 )
113+
114+ if j < len (self ._table ) and self ._table [j ]._key == k :
115+ j += 1
116+
117+ if j < len (self ._table ):
118+ return (self ._table [j ]._key , self ._table [j ]._value )
119+ else :
120+ return None
121+
122+ def find_range (self , start , stop ):
123+ """Iterate through all the (k,v) pairs such that start <= key < stop
124+
125+ if start is None, iterate from item with minimum key until stop
126+ if stop is None, iterate from item at start until the end of the map
127+ """
128+
129+ if start is None :
130+ j = 0
131+ else :
132+ j = self ._find_index (start , 0 , len (self ._table ) - 1 ) #find result
133+
134+ while j < len (self ._table ) and (stop is None or self ._table [j ]._key < stop ):
135+ yield (self ._table [j ]._key , self ._table [j ]._value )
136+ j += 1
0 commit comments