forked from tmoertel/recursion-to-iteration
-
Notifications
You must be signed in to change notification settings - Fork 0
/
exercise1.py
executable file
·75 lines (55 loc) · 1.88 KB
/
exercise1.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/env python
"""Recursion-to-Iteration Exercise 1
There are two recursive calls in find_val_or_next_smallest.
Can you create an equivalent function in which one of the
calls has been replaced by iteration? (Hint: Tail calls
are easier to replace.)
Can you create an equivalent function in which *both* of the
calls have been replaced by iteration?
For more information, see:
http://blog.moertel.com/tags/recursion-to-iteration%20series.html
Tom Moertel <[email protected]>
"""
class BSTNode(object):
"""Binary search tree node."""
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
def __repr__(self):
return '(%s, %r, %r)' % (self.val, self.left, self.right)
def find_val_or_next_smallest(bst, x):
"""Get the greatest value <= x in a binary search tree.
Returns None if no such value can be found.
"""
if bst is None:
return None
elif bst.val == x:
return x
elif bst.val > x:
return find_val_or_next_smallest(bst.left, x)
else:
right_best = find_val_or_next_smallest(bst.right, x)
if right_best is None:
return bst.val
return right_best
# tests
import bisect
tree0 = None
tree1 = BSTNode(5)
tree2 = BSTNode(5, BSTNode(3))
tree3 = BSTNode(5, BSTNode(3), BSTNode(9))
tree4 = BSTNode(5, BSTNode(3, BSTNode(1)), BSTNode(9))
trees = [tree0, tree1, tree2, tree3, tree4]
tree_vals = [[], [5], [3, 5], [3, 5, 9], [1, 3, 5, 9]]
def test():
for vals, bst in zip(tree_vals, trees):
for x in xrange(10):
y = find_val_or_next_smallest(bst, x)
if y is None:
assert all(x < z for z in vals)
else:
assert y <= x
if y != x:
i = bisect.bisect_right(vals, x)
assert all(x < z for z in vals[i:])