Question 1.
true: we can always simulate recursion using a stack that would essentially act as the activation stack built up by recursive calls. Note that we can directly simulate a tail recursive procedure without using a stack at all, as we did in class, but this does not mean we cannot simulate non-tail-recursive functions.

true: after all, a tree with one element is a BST. Or, think of a BST whose root has no left child.

false: consider the following traversals:
Preorder: 1 2 3
Postorder: 3 2 1

This preorder/postorder pair has two possible trees:
First tree: root is 1; left child of root is 2; left child of 2 is 3
Second tree: root is 1; right child of 1 is 2; right child of 2 is 3




-----

Question 2. see water.py




-----
Question 3. 
A. Benefits: exceptions can contain data, have callable methods, can be arranged in hierarchies for catching categories of exceptions, can reuse existing exceptions, can use inheritance

B. We are then tied to one particular implementation of a stack. If we change the stack code or use a new stack, our code will break; this would not happen if we used only the external interface of stack. Also, directly using the underlying list can allow us to do things that are not allowed on stacks (like removing elements from anywhere in the list, inserting elements anywhere in the list, etc.)


-----
Question 4.
Yes. Consider binary tree with root 2 and right child 3. 


-----
Question 5. See usesq.py. The output is:
3
3
