Here are suggested solutions to the exercises about search trees.
What you should notice is that for question A2, the binary search tree becomes extremely unbalanced, while the others do not because they are self-balancing!
smallest(tree) -> int
:
The smallest value is in the leftmost node, so go left until there are no more left children.
delete_minimum(tree) -> BST
:
If the leftmost node is a leaf, then we can just delete it.
Otherwise it must have one single right child (why?).
Now, reassign the parent of the smallest node to point to the right child.
delete(tree, value) -> BST
:
See the course book and the lecture slides for an implementation.
bst_to_list(tree) -> list of int
:
Call yourself recursively with the left child, and with the right child.
Then return the concatenation, but don’t forget to put the root node value in between the two lists.
union(s1, s2):
for each x in s2:
s1.add(x)
intersection(s1, s2):
for x in s1:
if not s2.contains(x):
s1.remove(x)
difference(s1, s2):
for x in s2:
s1.remove(x)
Bonus part: We will only show the solution for difference.
Here are two ways to implement set difference, with different complexities:
Suppose that s1 has size M and s2 has size N (note different notation from the question because we use capital N and M). Then method 1 takes time proportional to N log(M), while method 2 takes time proportional to M log(max(M, N)). Therefore, the solution is:
For a multiset: use a balanced BST map where the values are integers. Here are some possible operations:
count(x) -> int
: get the count of a particular element.
(Implementation: look up the key in the BST, return 0 if not found.)
Set-like operations, such as union and intersection. Typically for multisets we say e.g. that if S contains m copies of a key x, and T contains n copies of x, then S ∪ T should contain m+n copies of x.
union(other):
for key in other.keys():
if not this.contains(key):
this.put(key, 0)
this.put(key, this.get(key) + other.get(key)
For a multimap: use a balanced BST where the values are sets. Possible extra operations include:
valuesFor(x) -> Set
: return all values associated with a particular key.
(Implementation: look up the key in the BST, return the empty set if not found.)contains(x, v) -> boolean
: check if a given key-value pair is in the multimap.
(Implementation: look up the key in the BST to get a set of values, look up the value in that set.)class Multiset:
# e.g. using a map implemented using an AVL tree
map = new AVLTree()
add(x):
if map.contains(x):
count = map.get(x)
else:
count = 0
map.put(x, count + 1)
remove(x):
if map.contains(x):
count = map.get(x)
if count == 1:
map.remove(x)
else:
map.put(x, count - 1)
count(x) -> int:
if map.contains(x):
return map.get(x)
else:
return 0
contains(x) -> bool:
return count(x) != 0
# plus code for "union" from above
To be done.