6 # Copyright (c) 2010-2013 by Manfred Moitzi
9 from operator
import attrgetter
, lt
, gt
13 __slots__
= ['_node', '_stack', '_tree']
15 def __init__(self
, tree
):
17 self
._node
= tree
.root
22 self
._node
= self
._tree
.root
30 return self
._node
.value
34 return (self
._node
.key
, self
._node
.value
)
38 return self
._node
is not None
41 self
._node
= self
._tree
.root
42 while self
._node
is not None:
43 if key
== self
._node
.key
:
45 elif key
< self
._node
.key
:
52 self
._stack
.append(self
._node
)
55 self
._node
= self
._stack
.pop()
57 def stack_is_empty(self
):
58 return len(self
._stack
) == 0
61 """ get a leaf node """
62 while self
._node
is not None:
65 elif self
.has_right():
70 def has_child(self
, direction
):
72 return self
._node
.left
is not None
74 return self
._node
.right
is not None
76 def down(self
, direction
):
78 self
._node
= self
._node
.left
80 self
._node
= self
._node
.right
83 self
._node
= self
._node
.left
86 self
._node
= self
._node
.right
89 return self
._node
.left
is not None
92 return self
._node
.right
is not None
94 def _next_item(self
, key
, left
, right
, less_than
):
95 node
= self
._tree
.root
97 while node
is not None:
100 elif less_than(key
, node
.key
):
101 if (succ
is None) or less_than(node
.key
, succ
.key
):
107 if node
is None: # stay at dead end
108 raise KeyError(str(key
))
110 if right(node
) is not None:
111 # find smallest node of right subtree
113 while left(node
) is not None:
117 elif less_than(node
.key
, succ
.key
):
119 elif succ
is None: # given key is biggest in tree
120 raise KeyError(str(key
))
121 return (succ
.key
, succ
.value
)
123 def succ_item(self
, key
):
124 """ Get successor (k,v) pair of key, raises KeyError if key is max key
125 or key does not exist.
127 return self
._next
_item
(
129 left
=attrgetter("left"),
130 right
=attrgetter("right"),
134 def prev_item(self
, key
):
135 """ Get predecessor (k,v) pair of key, raises KeyError if key is min key
136 or key does not exist.
138 return self
._next
_item
(
140 left
=attrgetter("right"),
141 right
=attrgetter("left"),
145 def _iteritems(self
, left
=attrgetter("left"), right
=attrgetter("right")):
146 """ optimized forward iterator (reduced method calls) """
147 if self
._tree
.is_empty():
149 node
= self
._tree
.root
153 if left(node
) is not None and go_left
:
157 yield (node
.key
, node
.value
)
158 if right(node
) is not None:
167 def iter_items_forward(self
):
168 for item
in self
._iteritems
(
169 left
=attrgetter("left"),
170 right
=attrgetter("right"),
174 def iter_items_backward(self
):
175 for item
in self
._iteritems
(
176 left
=attrgetter("right"),
177 right
=attrgetter("left"),
181 def floor_item(self
, key
):
182 """ Get the element (k,v) pair associated with the greatest key less
183 than or equal to the given key, raises KeyError if there is no such key.
185 node
= self
._tree
.root
187 while node
is not None:
189 return node
.key
, node
.value
193 if (prev
is None) or (node
.key
> prev
.key
):
196 # node must be None here
198 return prev
.key
, prev
.value
199 raise KeyError(str(key
))
201 def ceiling_item(self
, key
):
202 """ Get the element (k,v) pair associated with the smallest key greater
203 than or equal to the given key, raises KeyError if there is no such key.
205 node
= self
._tree
.root
207 while node
is not None:
209 return node
.key
, node
.value
213 if (succ
is None) or (node
.key
< succ
.key
):
216 # node must be None here
218 return succ
.key
, succ
.value
219 raise KeyError(str(key
))