Homework set 4

Due Thursday, Apr 29.

Ex i.j denotes exercise j at end of chapter i.
Ex i.j.k denotes exercise k at end of chapter i, section j.

  1. 16.5.3
  2. 16.5.5
  3. 16.5.9 or 16.5.10 (your choice).
The next questions concern tree traversal. First study section 18.3 for ideas on setting up the statements about the state of the computation. Let us suppose we have binary trees implemented with the following functions:

If p is a tree whose nodes each holds a value of type T.
T root_value(tree p) // returns value stored at p's root.
tree & left(tree p) // p's left subtree
tree & right(tree p) // p's right subtree
bool empty(tree p) // true of an empty tree, no nodes
bool leaf(tree p) // true if p is not empty and both left(p) and right(p) are empty.

Note: this system allows left(p) and right(p) and root_value(p) to be valid on all trees including empty ones. The children of an empty tree are empty trees. The root_value of an empty tree is the default value of type T.

  1. Write a program, using loop(s) rather than recursion, to compute the number of leaves of a tree. Recursively, leaves(p) is
    1. 0 , if p is empty,
    2. 1 , if p is a leaf,
    3. leaves(left(p)) + leaves(right(p)), otherwise.
    Include overall precondition and postcondition, and, for each loop, an invariant and bound function. Give informal proof for any non-obvious item on the loop checklist.
  2. Define a tree p to be a full internal node if it is nonempty and both subtrees are nonempty, and to be a pass-thru node (or half-leaf), if one and only one of left(p) and right(p) is empty. Write an iterative program to compute, in one traversal of the tree, the number of full internal nodes, number of pass-thru nodes, and number of leaves. As before, include overall precondition and postcondition, and for each loop an invariant and bound function. Give informal proof for any non-obvious item on the loop checklist.

Postlude: A C++ impl of the tree data structure.
template< class T >
typedef node* tree;

template< class T >
struct node
{ tree* l; tree* r; T rv; 
  node(T& x = T(), tree& lt = NULL, tree& rt = NULL)): rv(x), l(lt), r(rt){} 
};

template< class T>
T root_value(tree t) {  return (t == NULL) ? T() : t->rv;  }

template< class T>
tree left(tree t) {  return (t == NULL) ? NULL : t->l;  }

template< class T>
tree right(tree t) {  return (t == NULL) ? NULL : t->r;  }

template< class T>
bool empty(tree t) {  return t == NULL; }  

template< class T >
bool leaf(tree t) {  return t != NULL && t->l == NULL && t->r == NULL; }  

template< class T >
tree singleton(T& x) { return new node(x); }

template< class T >
tree buildtree(T& x, tree& lt, tree& rt) { return new node(x, lt, rt); }