h5acct.c
, h5tree.h
, h5tree.c
,
and h5.scr
.
In this assignment you will implement a binary search tree. This will include implementing functions to create a tree, destroy it, add an element to the tree, delete an element, find an element in the tree and print out the elements of the tree.
You will use your binary search tree to build and manipulate a small account database. The account numbers will serve as the keys for your binary search tree. You will read the initial data for the account from a datafile, write functions which operate on the database once the initial tree has been built, and write out the changed database to an output file.
Your tree module must have the following interface:
typedef ?? treeKeyT; typedef ?? treeValueT; typedef struct { treeKeyT key; treeValueT value; } treeElementT; typedef struct treeCDT *treeADT; treeADT TreeCreate(void); void TreeDestroy(treeADT tree); void TreeAdd(treeADT tree, treeElementT element); treeElementT TreeDelete(treeADT tree, treeKeyT key); treeElementT *TreeFind(treeADT tree, treeKeyT key); void TreePrint(treeADT tree, FILE *outfileP);
Note that our elements now have 2 distinct parts. The key is the account number, the rest of the fields for an account (name and balance) form the value, which is the other part of a tree element. Your tree implementation can access the key and value, but may not access fields inside of those parts (since that would make the code less generic).
The interface must also contain the prototype for one more function:
/* * PrintElement is not defined here in the tree module, * it is only prototyped here. */ void PrintElement(treeElementT element, FILE *outfileP);
However, this last function must be defined in the main
program h5acct.c
, not in the implementation file. In
other words, the fact the the tree module only has a prototype for
PrintElement()
says that this function must be defined in
a main program in order to use the module.
The implementation file will need 2 types of its own:
typedef struct treeNodeTag { ... } treeNodeT; typedef struct treeCDT { ... } treeCDT;
Each treeNodeT will hold one element in the tree (linked) representation. The type treeCDT should hold the field(s) you need to keep track of a tree.
Only generic tree code should go in this tree module.
Code specific to the accounts (except for the type of things stored in
each account, which goes in h5tree.h
) should go in the
main program h5acct.c
.
You must submit files h5tree.h
, containing the interface,
and h5tree.c
, containing the implementation.
A simple test program,
/cs/course/cs113/current/hw5/h5treetest.c
, is available
for you to test your tree module. We strongly
suggest that you compile and run your tree module with this code to
help ensure your code works properly and that it is generic (i.e.,
note that the test program uses a different kind of key
and value).
When the program starts, it should read in the initial set of accounts
from the data file /cs/course/cs113/current/hw5/accounts.in
.
It should do this by opening the file with fopen()
.
reading from it, etc. Examine that file to determine the format of
account data (there is one account per line).
Once the initial accounts are read in, you should repeatedly prompted the user, allowing them to enter commands to:
TreePrint
).
TreePrint
to print to this file).
Your program should print prompts and label its output.
You may assume that fields will be entered correctly, i.e., account numbers and balances will only have digits in them.
Remember that the function PrintElement
, which must
take an account (i.e., an element) and print out its fields in
a reasonable manner, must be defined in this main program.
Add the following types to your main program (after you include
h5tree.h
):
typedef treeElementT accountT; typedef treeKeyT acctNumT;
That way you can declare account variables with more descriptive types in the main program. I.e., you can do:
accountT acct1; acctNumT acct_num; acct1.key = 4567; strcpy(acct1.value.name, name); acct1.value.balance = 789; acct_num = acct1.key;
You must submit a file named h5acct.c
that contains this
main program.
Here is how each tree function should operate and how it will be used in the main program:
TreeCreate()
: Should set up a new empty tree.
treeADT tree; ... tree = TreeCreate();
TreeDestroy
: Gets rid of all the memory being used by
the tree. Use this function something like:
TreeDestroy(tree);
TreeAdd
: Should add an account to the tree given the
specified account (i.e., an element). Remember that the tree should
maintain the binary search tree property after the element has
been added. Use this function something like:
accountT account; /* Set up the acct num, name and balance fields of the account. */ TreeAdd(tree, account);
If an account with that key (i.e., account number) is already in the tree, replace its old information with this new information. If not, you must add this new account to the tree (use dynamic allocation to create a new node).
TreeDelete
: Should remove a certain account from the tree
given its acct num. Remember that the tree should maintain the binary
search tree property after the element has been removed. Use this
function something like:
acctNumT acct_num; accountT account; /* Set up the account number for the account you want to delete. */ account = TreeDelete(tree, acct_num);
This requires removing a node from the tree. The information for that account should be returned from this function.
If an account with that number is not present in the tree, this tree function should print out a generic message saying it is not there and exit the program. (The tree's message should be generic since it doesn't know it is storing accounts).
Your main program should prevent this tree delete error message from ever happening. I.e., you can call "TreeFind" to make sure something is in the tree before you try to delete it. If it's not present, print out your own error message in the main program.
TreeFind
: Searches the tree to see if an element is
present. If so, returns a pointer to that element.
You'll use it something like:
accountT *acctP; acctNumT acct_num; /* Set up the account number. */ acctP = TreeFind(tree, acct_num); if (acctP != NULL) { /* Deal with account. */ }
Finding something in a tree was described in discussion sections (see the Binary Tree lab). However, remember that this homeworks uses a binary search tree, not a generic binary tree, so searching is done differently than in that lab.
TreePrint
: Should print out each account in the tree.
This function must perform a preorder traversal (left to right).
Since a generic tree data structure cannot possibly know how
to print out an account, it will just call a function
PrintElement
, which will be defined in the main program,
which knows how to print out an account.
You'll use TreePrint
something like:
TreePrint(tree, fileP); ... /* PrintElement defined below. */
/cs/course/cs113/current/hw5/h5makefile
.
h5.scr
) must contain: each source code
file (use "cat" to display each), compilation (using our make file)
and a test run.
You must have 1 test run, which you construct on your own. It should
demonstrate each of the account commands, including error handling. The
first thing the test run should do is print out the tree (right after
the accounts have been read in from the initial file). After you exit
the program, cat
the file "accounts.out" so that we can
see what was written out.