33B. Trees in C++


The Node and Tree types

The following types are suitable for representing a tree that has an integer stored at each node. An object of type Node represents one node in a binary tree. It holds an integer item, a pointer to the left subtree and a pointer to the right subtree. Those pointers can be NULL to indicate an empty subtree.

Note that type Tree is identical to type Node*. An empty tree is represented by a NULL pointer.

  struct Node
  {
    int   item;      // Information at this node
    Node* left;      // The left subtree
    Node* right;     // The right subtree

    Node(int it, Node* lft, Node* rgt)
    {
      item  = it;
      left  = lft;
      right = rgt;
    }
  };

  typedef Node* Tree;
  typedef const Node* ConstTree;

Nondestructive functions on trees

As for linked lists, we can separate functions on trees into nondestructive functions, which do not alter a tree, and destructive functions, which do.

A simple nondestructive function is numNodes(T ), which yields the number of nodes in tree T. The algorithm breaks down naturally into two cases: an empty tree (NULL) and a nonempty tree.

  1. If T is empty then T has 0 nodes.

  2. If T  is nonempty then T  has its root (one node) plus all of the nodes in the left subtree plus all of the nodes in the right subtree.

Putting those ideas into a definition of numNodes(T ) yields the following.

  int numNodes(ConstTree T)
  {
    if(T == NULL)
    {
      return 0;
    }
    else
    {
      return 1 + numNodes(T->left) + numNodes(T->right);
    }
  }

Another example of a nondestructive function on trees is cubes(T ), which returns a tree that looks like T  except that each number is replaced by its cube. For example, if T is

then cubes(T ) yields the following tree, without modifying T.

  int cube(int x)
  {
    return x*x*x;
  }

  Tree cubes(ConstTree T)
  {
    if(T == NULL)
    {
      return NULL;
    }
    else 
    {
      return new Node(cube(T->item), cubes(T->left), cubes(T->right));
    }
  }

Destructive functions on trees

A destructive function modifies a tree. For example, the following function replaces each item in a tree by its cube.

  void cubeAll(Tree T)
  {
    if(T != NULL)
    {
      T->item = cube(T->item);
      cubeAll(T->left);
      cubeAll(T->right);
    }
  }
Note that T does not need to be passed by reference to cubeAll because cubeAll does not need to change the pointer T. It only changes the node to which T points (and other nodes in subtrees). So cubeAll uses call by pointer. But some functions do need to use call by reference, since they need to store a different pointer into a variable. We will see some examples of that shortly.


Exercises

  1. Write a definition of function numLeaves(T ), which returns the number of leaves in tree T. Answer

  2. Write a definition of a function sum(T ) that returns the sum of all of the numbers in a given tree. If T is empty then sum(T ) is 0. Answer

  3. Write a definition of function nonneg(T ), which produces the tree that results by replacing each negative number in T by 0, and leaves nonnegative numbers as they were. For example, if T is the left-hand tree below then nonneg(T ) is the right-hand tree.

    This function must not modify T. The result tree should be made out of new nodes.

    Answer

  4. Write a definition of function mirror(T ), which produces a mirror image of tree T. To get the mirror image, imagine picking the tree up with a spatula and flipping it over. For example, the following two trees are mirror images of one another.

    This function must not modify T. The result tree should be made out of new nodes.

    Answer

  5. Read the definition of the height of a tree. Write a function height(T ) that returns the height of tree T. Answer

  6. The mirror image of a tree is defined in question 4. Write a definition of function flip(T ) that changes T into its mirror image. This is a destructive function. Answer

  7. Why doesn't the parameter of flip in the preceding question need to be passed by reference? Answer

  8. Write a definition of function destroy(T ), which deletes every node in tree T. Answer