CS 2005 Techniques of Programming WPI, B Term 1996
Craig E. Wills Project 4 (25 pts)
Assigned: Tuesday, December 10, 1996 Due: Friday (11:59pm), December 20, 1996

Introduction

This assignment is designed for you to put into practice the concept of trees and recursion. Your group will design and implement a set of routines to build and manipulate trees. The driver program will be provided to you.

Objectives

Rather than implementing binary trees where a node can have no more than two children, you will be implementing trees where a node may have any number of children. For example, a hierarchical file system is a tree where each directory can contain any number of files. One organization for storing trees of this type is for each node to have a pointer to the leftmost child and have a pointer to the next sibling. This organization leads to the following C structure definition for a tree node (all node values will be characters). This structure is defined in the file /cs/cs2005/pub/example/proj4tree.h.

struct TreeNodeType {
    char chNode;                /* value of the node */
    TreeNodeType *pTreeLeft; /* pointer to leftmost child */
    TreeNodeType *pTreeNext; /* pointer to next sibling */
};

Driver Program

The driver program for your program is in the file /cs/cs2005/pub/example/proj4tree.C (note that we will just be using structures and functions, not classes on this assignment). You should copy this file to your group directory and then create other modules containing the code for the tree manipulation routines. You should create a Makefile that ties all the modules together.

The main interface of your program will implement the following tree-based commands:

Commands (shortened versions of command names can be used, 
node values are characters):
addnode x y  -- add the node y with parent x to the tree
deletenode x -- delete the node x from the tree, x must be a leaf node
exist x -- indicate whether the node currently exists in the tree
height -- show the height of the tree
leaf -- show the number of leaf nodes in the tree
menu -- print this menu
node -- show the number of nodes in the tree
parent x -- show the parent of the node x
quit -- quit the program
show -- show the contents of the entire tree

Command-Line Arguments

It is possible in the Unix environment to pass strings given in the command line to your program. This is a useful way of passing values to your program without recompiling it each time or reading from standard input. In the proj4tree.C file is the following code to use these values for passing a data file name.

main(int argc, char *argv[])
{
    TreeNodeType *pTreeRoot;        /* root of the tree */
    /* stuff deleted */

    pTreeRoot = NULL;                /* initialize the tree */
    if (argc >= 2) {
        if (ReadTree(pTreeRoot, argv[1]) < 0) {
            cout << "Initialization of the tree from file " <<
                argv[1] << " failed.\n";
            exit(1);
        }
    }

This code shows that main() has two arguments--an argument count argc, which is an integer and an argument vector argv, which is a NULL-terminated array of strings. These variables are automatically initialized at program execution. For the command line

> proj4tree treedata

the value of argc will be 2 (the command itself counts as an argument), the value of argv[0] will be the string "proj4tree", the value of argv[1] will be the string "treedata" and the value of argv[2] will be NULL. Thus in the program, if a second argument is given, it is assumed to be a data file name that is passed to the ReadTree() routine for initializing the tree. If there is not a second argument then the tree is initially NULL.

Tree Creation

Using the command line shown above with the file treedata containing the following values, the tree shown in Figure 1 should be built. Each line is one set of arguments to AddNode(). Figure 1 also shows the node structure for this tree using the TreeNodeType structure. A couple notes:

* A
A B
A C
A D
B E
B F
C G
G H
E L

  figure28
Figure: Sample Tree and Internal Organization  

Tree Routines (Your Work)

The driver is already written. Your job is to write the following set of routines and link them with the driver. Most of the routines (with the exception of AddNode() and perhaps DeleteNode()) are best written recursively. You may create additional routines if needed. You must use these parameters and return values as they match those in proj4tree.C. You should note that both AddNode() and DeleteNode() require the pointer to the root of the tree to be passed by reference. This is required in case the root of the tree must be changed. See the corresponding call in proj4tree.C. All return errors (such as EEXIST) are defined in proj4tree.h. These routine definitions are in /cs/cs2005/pub/example/proj4treeaux.C.

/*
 * MakeTreeNode -- make a tree node.  Return pointer to node on success and
 *      NULL on failure.
 */
TreeNodeType *MakeTreeNode(char chNode)

/*
 * FindParentNode -- recursively find the parent of the node with the given 
 *      value, return NULL on failure or if the node is the root
 */
TreeNodeType *FindParentNode(TreeNodeType *pTreeRoot, char chNode)

/*
 * FindNode -- recursively find the node with the given value, return NULL
 *      on failure
 */
TreeNodeType *FindNode(TreeNodeType *pTreeRoot, char chNode)

/*
 * AddNode -- add the given node as a child of the parent.  If the parent is
 *      ROOT then this node is the root of the tree.  Return 0 on success,
 *      EEXIST if the node already exists in the tree
 *      EMULTROOT if a root node is being added and one already exists
 *      EPARENT if the parent node does not exist in the tree
 *      ENOMEMORY if no memory exists to create a node
 */
int AddNode(TreeNodeType * &pTreeRoot, char chParent, char chNode)

/*
 * DeleteNode -- Delete the given node, which must be a leaf.  Return 0 on 
 *      success, ENOTLEAF if the node exists but is not a leaf and 
 *      ENOEXIST if the node does not exist.
 */
int DeleteNode(TreeNodeType * &pTreeRoot, char chNode)

/*
 * ShowTree -- recursively print the tree with space indentation 
 *      corresponding to the level of the node.
 */
void ShowTree(TreeNodeType *pTreeRoot, int wLevel)

/*
 * ComputeHeight -- recursively compute the height of the tree
 */
int ComputeHeight(TreeNodeType *pTreeRoot)

/*
 * CountNode -- recursively compute the number of nodes
 */
int CountNode(TreeNodeType *pTreeRoot)

/*
 * CountLeafNode -- recursively compute the number of leaf nodes
 */
int CountLeafNode(TreeNodeType *pTreeRoot)

Sample Script

The following is a sample script using the sample tree data defined previously. Note that commands can be abbreviated to one character.

> proj4tree treedata
Command (a,d,e,h,l,m,n,p,q,s): s
A
 D
 C
  G
   H
 B
  F
  E
   L
Command (a,d,e,h,l,m,n,p,q,s): a D Q
Add of Q succeeded
Command (a,d,e,h,l,m,n,p,q,s): a P S
Add failed, parent node P not found
Command (a,d,e,h,l,m,n,p,q,s): d C
Delete failed, node C is not a leaf
Command (a,d,e,h,l,m,n,p,q,s): d F
Deletion of F succeeded
Command (a,d,e,h,l,m,n,p,q,s): s
A
 D
  Q
 C
  G
   H
 B
  E
   L
Command (a,d,e,h,l,m,n,p,q,s): e L
Node L does exist in tree
Command (a,d,e,h,l,m,n,p,q,s): p L
Parent of node L is E
Command (a,d,e,h,l,m,n,p,q,s): n
The number of nodes in the tree is 9
Command (a,d,e,h,l,m,n,p,q,s): l
The number of leaf nodes in the tree is 3
Command (a,d,e,h,l,m,n,p,q,s): h
The height of the tree is 3
Command (a,d,e,h,l,m,n,p,q,s): q

Group Organization

You should discuss the overall organization of the program and make sure that each member of the group understands the overall task to be done. You should also discuss the specifics of each routine that needs to be done. If your group does not understand some aspect of the project you should consult with your PLA, a TA or the instructor. After the discussion your group should break the implementation into pieces. Each group member should implement a portion of the routines. The most crucial routines will be AddNode(), which may use FindNode(), to build the tree and ShowTree() to print out the tree. The other routines can be tested after these routines are built. The DeleteNode() routine will probably be the most difficult to implement.

Each person should implement the routines assigned to them as an individual module. All modules and the driver should be compiled and linked with a Makefile. All modules should contain the header file. You are responsible for testing your program on a variety of input data.

Submission

You will be turning in your project as a group using the gturnin command (for ``proj4''). You will also turnin (for ``proj4eval'') an individual assessment of your groups' efforts as done in the previous assignment. Again, you are expected to talk as a group about each member's contributions before submitting your individual assessments.