CS 370 Lab #5: Trees

In this lab, you will consider the beauty and virtue of the tree abstract data type. The main operations are creation (including establishing pointers to one's children and possibly parents) and traversal.

Here is a sample tree structure, about as simple as we can plan to make it.

typedef struct node {
   int label;
   int num_kids;
   struct node *kids[9]; /* at most 9 children/node or we're in trouble */
   } node, *nodeptr;
Note that "node" is a shorthand name for struct node, and "nodeptr" is a shorthand name for (struct node *). Now, we need functions to create and initialize two types of tree nodes: leaves and internal nodes.

Complete the following exercises. Turn in an electronic copy of your solutions.

1. Write a tree.h file that contains the typedef for a struct pointer (nodeptr) for tree structures. In addition to the typedef, include prototypes for your tree functions as defined below. Since you have a typedef, if some .c file accidentally #include's your .h file twice they will get a syntax error! Protect your header file with a prefix and suffix as follows:

#ifndef TREE_H
#define TREE_H
...tree header file contents
#endif
The rest of this lab will go in a corresponding tree.c file. Unfortunately, C does not (easily) let us use trees from other modules without knowing their implementation details. If you did want to practice such information hiding in C, how would you go about it?

2. Write a tree node constructor function or functions. Offhand I see the largest grammar rule has 7-8 symbols on its right hand side, so you can either use a variable arguments tree constructor like the one from lecture notes, or write 9 separate tree constructor functions with # of children ranging from 0-8. Whichever way you do it, the constructor(s) should allocate sufficient memory and then initialize that memory with values and pointers to children, passed in parameters.

3. Write tree node traversal functions. Functions preorder(t,f), postorder(t,f) and inorder(t,f) should take a tree node pointer t and a function f, and call that function on each node in t in either pre-, post-, or in-order traversals.

4. Write a simple tree printer helper function nodeprint(t), that prints useful information about tree node t (such as its nonterminal rule # or its lexical information), followed by a newline.

5. Test your work. Build a sample tree by hardwired calls to your tree constructor functions, say for x+y*z. Call postorder(t, nodeprint) such that you will get a printout like:

x
y
z
*
+
Note: you will work with trees a lot in the next few weeks.