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:

  1. The ability to read from text files.
  2. The recursive implementation of the shift method.
  3. Timing programs.
  4. Designing an effective, flexible, interface.
  5. Carrying out a reasonable experiment to test the algorithms.
  6. 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).