Computer Science 210 Lab 4: Complexity
Due: October 5, 1999
Objectives and Overview: In this lab we are going
to experiment with different algorithms in order to
better understand the impact of algorithm design on time
complexity. At the same time we will gain experience with
recursion, as well as learn how to work with files in Java and
to get a first exposure to sorting.
The return of WordFreq: Reading from files.
We will reuse the WordFreq program from lab 2, as well
as the Vector class in this lab. Your first task will
be to adapt the WordFreq program to read from files rather
than from the keyboard. To do this, the first step is to
make the first line of your program
import java.io.*;
This gives your program access to Java's file routines.
Next you will need an "InputStream" object. This can
be obtained with a statement such as
InputStream istream = new InputStream(filename);
where filename is a String with the value of the
name of the file you want to read. Finally, after that
you alter your initialization of the ReadStream object
as follows:
ReadStream r = new ReadStream(istream);
Essentially, this tells ReadStream to go looking for
its input from the file you have specified. The operations
on that file can be just like those on the keyboard (with
one happy exception - the eof will work with files).
It is important to note that, as with most objects, you
can have multiple ReadStream objects. So you could open
a second stream in order to read input from the keyboard
for example.
Experiment with some small text files. An easy way to
make a file is within Code Warrior. Just issue the
new command from the File menu and a
file will be created. Once you fill in some text and
save the file you can read from it.
Timing programs.
One useful thing to do when studying complexity is to
look at exactly how long programs and methods take to run.
Java provides a handy method to do this. This method
requires that your program have the following statement
with its other import statements:
import java.util.*;
The method is called System.currentTimeMillis() and it
returns a long which is the current time. So to time
a method (in this case BubbleSort) one might do the following:
long t1 = System.currentTimeMillis();
x.BubbleSort(data);
long t2 = System.currentTimeMillis();
System.out.println("The time taken was "+ t2 - t1 +" milliseconds");
For this lab you will want to compare different strategies
by timing their performance.
Recursion
A common task in the Vector methods is shifting parts of
the Vector in one direction or the either. For example,
when insertElementAt is called, the end of the Vector is
shifted down a place to make room for the new element.
Conversely, in removeElementAt the end of the Vector
must be shifted up to replace the old element.
Write a shift method for the Vector class. The method
should specify a target slot in the Vector as well as
a direction to shift. The shift method must be written
recursively.
Once you've done that, write two new methods with the
same functionality as insertElementAt and removeElementAt,
but which make use of the shift method, instead of
loops.
Once you've debugged those test their speed against the
speed of the original methods. Make sure the test
is fair (e.g. use the same data on each run). It would
be best to run several tests and take the average performance
over all of them.
Sorting
In lab2 you wrote an insertOrdered method. In that
method you kept the Vector sorted as you entered
new items. Another approach would be to read in
all of the items and then sort it afterwards. I
have provided code for a sorting method called
VectorInsertionSort which can be used for this
approach. Test out each method and evaluate their
performance. For this part I reccomend using
a large file, such as the "empire" file I have
provided.
Deliverables
An "A" program is flexible enough to be able to do
any of the tests. It would have the user select
what test to run (ideally, even the file to read
from) and print the results of the test in an
easy to read format. E.g. the user could set
recursive vs. loop, insert at read vs. sort,
and a file to run on. The program would then
execute and print how long the test took. It
also might have a mode where all four possibilities
are handled iteratively (recursive/read, recursive/sort,
loop/read, loop/sort) and then summarized.
In addition, I am going to start taking readability
seriously with this lab. Your code should be
well commented and well indented.
To summarize, the important factors on this lab are:
- The ability to read from text files.
- The recursive implementation of the shift method.
- Timing programs.
- Designing an effective, flexible, interface.
- Carrying out a reasonable experiment to test the algorithms.
- Readability.
I need hardcopies of your code (with copies in the
drop box with the usual naming convention) as well
as output showing the comparisons of each of the
main tests (loops vs. recursion, sorting versus
inserting at read time). Also, tell me what the
ideal configuration of the program is and explain
why it seems to be best ("its fastest" isn't an
answer, I want to know why it is fastest).