CS211 - Algorithms and Data Structures II
Department of Computer Science, NUIM
Laboratory Sheet 8
For week beginning Monday 20 March 2000
T. Naughton, CS NUIM
In this laboratory you will learn to manipulate binary trees. There are two programs to write, Problems 8.1 and 8.2. Show a demonstrator a working solution to each problem to get a credit. When finished, start on the list of problems at the end of this lab sheet.
Note: Twenty minutes before the end of the lab, demonstrators will concentrate on correcting your solutions. They will not answer questions from this time.
Lab Sheet 8
Because of their recursive structure, tree manipulation tasks are often most easily expressed as recursive algorithms. To get you used to recursive definitions, here are recursive algorithms for some methods you have already coded iteratively.
bool IntList::Contains(ListElement * current, int value){ These recursive definitions, however, do have some undesirable features. Although Contains() works identically to its iterative counterpart, PrintList() does not output the "Here is the list:" comment. Can you see why this cannot easily be put in the recursive function?
More importantly, the recursive definition of DeleteList() shown above can, under some circumstances, cause a runtime error. Although it does delete all nodes, and will work perfectly as a destructor, it does not set head=NULL afterwards. (Look at the pictures, they'll show this to you!)
For this reason, we will wrap all recursive methods in an extra method that takes care of additional tasks (such as writing a comment to the screen, setting head=NULL) and special cases (such as adding to an empty list). As an added bonus we find that our recursive and iterative implementations of the class will now have identical interfaces (if you do not know what this means, the so called "interface-implementation separation", find out now -- re-read your CS210 notes). The user will then not have to pass the head of the list to Contains(), PrintList(), or DeleteList() as shown above; they may call the method as if it were an iterative implementation.
A program that implements all of these ideas is given here. Make sure you understand it before continuing.
In order to implement an ordered binary tree to store integers, the following first steps must be taken.
Problem 8.1 Implement these first three steps (above). If you understand linked lists it should be easy. If you have to ask for a demonstrator's help then you don't understand linked lists!
Next, we can implement some basic methods. (You should have some practice drawing the pictures from the last lab.)
To help you along, here is a recursive algorithm for the second one: Problem 8.2 Implement these three methods (above). Call a demonstrator when you have finished all three.
Of course, it will not be possible to test these methods until we are capable of adding nodes to a tree. When you are finished Problems 8.1 and 8.2, and got your two credits for this lab session, try Problem 8.3.
Problem 8.3 Enhance your solution to Problem 8.2 with the following methods:
End of Lab Sheet
if (current == NULL) {
return false;
} else if (current->data == value) {
return true;
} else {
return Contains(current->next, value);
}
}
void IntList::PrintList(ListElement * current){
if (current != NULL) {
cout << current->data << ' ';
PrintList(current->next);
}
}
void IntList::DeleteList(ListElement * current){
// Delete nodes from the tail to the head
if (current != NULL) {
DeleteListRec(current->next);
delete current;
}
}
bool OrdIntTree::Contains(BinTreeElement * current, int value){
//if current is NULL (i.e. we've reached the end of a subtree) then return false
//otherwise, if the current node contains the value then return true
//otherwise, if it's in the left subtree or in the right subtree then return true
}