CSE 326: Data Structures
Assignment #4
April 29, 1999
Due: Monday, May 10
(Note that the some web browsers do not display mathematical equations correctly. If you have problems, you should consult the postscript version of this homework.)
For this assignment you will be implementing a Dictionary class using splay trees, and experimenting with it.
Implement the procedures Rotate, Splay, Lookup, Insert, Concat, Delete, FindMin and FindMax as described in the handout and lecture from scratch. With the exception of Splay, these procedures are very short and easy, so don't be concerned about the number of procedures you have to implement. The procedures Lookup, Insert and Delete should all be public members of your Dictionary class. You are free to modify the interface and implementation of the private members, as long as they accomplish their task by the same algorithms given in the handout.
For the experiments you will be performing, the data type for the Key field will be int and the Info field will be unused (but should be available). In this case, Lookup should simply return a boolean that is true if and only if the key was found.
Your implementation of Splay should be iterative (non-recursive) and should not use an explicit stack. It will be convenient to have each tree node contain an extra field which contains a pointer to its parent in the tree.
Your main program should consist of an empirical evaluation of the performance of your Dictionary ADT.
Generate at least three different long sequences of insertion, deletion and lookup operations. Each sequence should consist of at least 500,000 operations, starting from an empty tree, and should result in trees with at least 100,000 nodes (at maximum size). For each sequence of operations, compute the total number of rotations your implementation performs to execute all the operations, and the ratio between this number and mlogn, where m is the number of operations in the sequence and n is the maximum size the tree ever gets over the course of executing the sequence.
Turn in an electronic copy of your source code, along with your Makefile. You program must be able to be run by executing make and then splay-trees. You can do this by running the turnin program on orcas as:
turnin -v -c cse326 Makefile *.cpp *.hor a whole directory with:
turnin -v -c cse326 hw4/
Feel free to turn in a README file as well. It is very important that you turn in all of your files at once. If you forget some files the first time then turn everything in again. The turnin program only keeps your last turn in. Do not turn in object files .o or your compiled main programs.
The paper turnin should contain the following:
For extra credit, you can do the following:
Hint: Because the type of rotation done depends on the path to P from the grandparent of P, you need some ancestral context after returning from a recursive call. Design your procedure so that when the recursive call returns, P is either at depth 1 or depth 2 from the current root. If it is at depth 1, then simply return without doing any rotation; if at depth 2, then do the appropriate two rotations before returning. If P is at depth 1, you may want your recursive call to return the direction (left or right) to P, to help the recursive invocation find P from its current root. Notice that when all the recursion ends, P may be left at depth 1 of the entire tree, so some Case I cleanup may be necessary.
Warning: It may occur to you that each recursive call could leap down 2 levels rather than 1, and then do the obvious Case II or Case III rotation when the recursive call returns. This won't work. The problem is that, if the path length to the splayed node is odd, then you will do the Case I rotation as the very first rotation rather than the very last. This results in entirely different splay behavior than the algorithm handed out, and we cannot give you any guarantee that the amortized analysis holds anymore.