Skip to content

Commit b1c3159

Browse files
authored
Add upper and lower bound in BST (#537)
1 parent c7b2af7 commit b1c3159

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

pydatastructs/trees/binary_trees.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,98 @@ def search(self, key, **kwargs):
275275
walk = self.tree[walk].right
276276
return (walk, parent) if ret_parent else walk
277277

278+
def _bound_helper(self, node_idx, bound_key, is_upper=False):
279+
if node_idx is None:
280+
return None
281+
if self.tree[node_idx].key is None:
282+
return None
283+
284+
if self.tree[node_idx].key == bound_key:
285+
if not is_upper:
286+
return self.tree[node_idx].key
287+
else:
288+
return self._bound_helper(self.tree[node_idx].right,
289+
bound_key, is_upper)
290+
291+
if self.comparator(self.tree[node_idx].key, bound_key):
292+
return self._bound_helper(self.tree[node_idx].right,
293+
bound_key, is_upper)
294+
else:
295+
res_bound = self._bound_helper(self.tree[node_idx].left,
296+
bound_key, is_upper)
297+
return res_bound if res_bound is not None else self.tree[node_idx].key
298+
299+
300+
def lower_bound(self, key, **kwargs):
301+
"""
302+
Finds the lower bound of the given key in the tree
303+
304+
Parameters
305+
==========
306+
307+
key
308+
The key for comparison
309+
310+
Examples
311+
========
312+
313+
>>> from pydatastructs.trees import BinarySearchTree as BST
314+
>>> b = BST()
315+
>>> b.insert(10, 10)
316+
>>> b.insert(18, 18)
317+
>>> b.insert(7, 7)
318+
>>> b.lower_bound(9)
319+
10
320+
>>> b.lower_bound(7)
321+
7
322+
>>> b.lower_bound(20) is None
323+
True
324+
325+
Returns
326+
=======
327+
328+
value
329+
The lower bound of the given key.
330+
Returns None if the value doesn't exist
331+
"""
332+
return self._bound_helper(self.root_idx, key)
333+
334+
335+
def upper_bound(self, key, **kwargs):
336+
"""
337+
Finds the upper bound of the given key in the tree
338+
339+
Parameters
340+
==========
341+
342+
key
343+
The key for comparison
344+
345+
Examples
346+
========
347+
348+
>>> from pydatastructs.trees import BinarySearchTree as BST
349+
>>> b = BST()
350+
>>> b.insert(10, 10)
351+
>>> b.insert(18, 18)
352+
>>> b.insert(7, 7)
353+
>>> b.upper_bound(9)
354+
10
355+
>>> b.upper_bound(7)
356+
10
357+
>>> b.upper_bound(20) is None
358+
True
359+
360+
Returns
361+
=======
362+
363+
value
364+
The upper bound of the given key.
365+
Returns None if the value doesn't exist
366+
"""
367+
return self._bound_helper(self.root_idx, key, True)
368+
369+
278370
def delete(self, key, **kwargs):
279371
(walk, parent) = self.search(key, parent=True)
280372
a = None

pydatastructs/trees/tests/test_binary_trees.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,31 @@ def test_RedBlackTree():
525525
assert [node.key for node in in_order] == [2, 6, 7, 10, 15, 16, 17, 18, 25, 30, 40, 60]
526526
assert [node.key for node in pre_order] == [16, 10, 6, 2, 7, 15, 25, 18, 17, 40, 30, 60]
527527

528+
assert tree.lower_bound(0) == 2
529+
assert tree.lower_bound(2) == 2
530+
assert tree.lower_bound(3) == 6
531+
assert tree.lower_bound(7) == 7
532+
assert tree.lower_bound(25) == 25
533+
assert tree.lower_bound(32) == 40
534+
assert tree.lower_bound(41) == 60
535+
assert tree.lower_bound(60) == 60
536+
assert tree.lower_bound(61) is None
537+
538+
assert tree.upper_bound(0) == 2
539+
assert tree.upper_bound(2) == 6
540+
assert tree.upper_bound(3) == 6
541+
assert tree.upper_bound(7) == 10
542+
assert tree.upper_bound(25) == 30
543+
assert tree.upper_bound(32) == 40
544+
assert tree.upper_bound(41) == 60
545+
assert tree.upper_bound(60) is None
546+
assert tree.upper_bound(61) is None
547+
528548
tree = RedBlackTree()
549+
550+
assert tree.lower_bound(1) is None
551+
assert tree.upper_bound(0) is None
552+
529553
tree.insert(10)
530554
tree.insert(20)
531555
tree.insert(30)

0 commit comments

Comments
 (0)