15-121 SPRING 2010 [CORTINA]

HOMEWORK 5 - due Tuesday, February 23

WRITTEN PROBLEMS (10 points)

  1. (1 pt) Recall in class that the SinglyLinkedList class consists of a reference to the head of the list only. If the list has n nodes, adding or removing from the end of the list takes O(n) time since you have to traverse the entire list to find the last node. Suppose we store references to the head and tail of the list instead of just the head of the list. What is the worst case runtime complexity for adding to the end of the list and removing from the end of the list as a function of n? Explain.

  2. (1.5 pts) Let the DoublyLinkedList<E> class represent a doubly linked list with a reference to the head node and a reference to the tail node, both of type Node<E>. Each node has a data field of type E and two Node<E> references named prev and next. The Node<E> class is defined as an inner class of DoublyLinkedList<E>. Write a method for this class named remove that takes an index of a node of the list and removes the node from the list and returns a reference to its data. A valid index is between 0 and the size of the list minus 1. If the index is invalid, throw an exception instead.

  3. (1.5 pts) Consider a variant of the singly linked list that contains a "dummy node" at the beginning of the list with no data (i.e. the data field is always null). An empty list consists of a dummy node only. A list with n elements has n+1 nodes, the first node being the dummy node. The dummy node makes it easier to implement add and remove operations since the list can never be truly empty.

    1. Rewrite the constructor for SinglyLinkedList so it creates an "empty" list consisting of one dummy node.

    2. Rewrite the methods add and remove assuming the singly linked list always contains a dummy node.

  4. (1.5 pts) Write a Java method that prints out the contents of a singly-linked list in reverse order using O(1) additional storage. You may assume that this method is part of the SinglyLinkedList class. When we say "using O(1) additional storage", we mean that the amount of extra memory used is not dependent on the size of the list. Explain why your method only uses a constant amount of extra storage space. What is the runtime complexity of your algorithm using big-O notation in terms of n? Justify your answer.

    Special note to those who know about recursion: This method should not be recursive because recursion requires the use of the system stack which will grow proportionally to the size of the linked list.

  5. (1 pt) See the description of a sparse matrix in the programming assignment below. Assume that each int takes 4 bytes and each object reference takes 8 bytes. You want to store an 200 × 200 matrix using either a two-dimensional array or a sparse matrix as defined below. A two-dimensional array stores its values in sequential memory locations row by row with no additional memory required. What is the maximum number of nonzero values that can be stored in the matrix so that the sparse matrix uses less memory than the two-dimensional array? Show your work.

  6. (1 pt) Smithers decides to implement his own stack, called SmithersStack<E>. The contents of the stack are stored in a field called data of type ArrayList<E>, where INDEX 0 represents the TOP of the stack.

    public class SmithersStack<E>
    {
            private ArrayList<E> data;  //top element at index 0
    
            //constructors and other methods not shown
    }
    

    1. Complete the pop method for the SmithersStack class and determine the worst-case runtime complexity of pop assuming that the stack contains n elements. If the stack is empty, return null in this case.

    2. Complete the push method for the SmithersStack class and determine the worst-case runtime complexity of push assuming that the stack contains n elements.

  7. (1 pt) Complete the method below, which should return a new stack containing the playing cards in the given stack in the same order, with all aces removed.

    public static LIFOStack<PlayingCard> removeAces(LIFOStack<PlayingCard> s)
    {
    
    }
    

  8. (1.5 pts)
    1. The infix-to-postfix converter discussed in class translates an infix expression to the equivalent postfix expression using a stack. Convert the following infix expression to a postfix expression and show the contents of the stack (from top to bottom) and the resulting postfix string after each operator is processed.

      4 + 3 + ( 7 - 4 / 2 ) * 5 - ( ( 2 + 1 ) * 6 ) * 9 - 8
      

    2. The postfix evaluator discussed in class computes the value of any valid postfix expression using a stack. What is the value of the following postfix expression? Show the contents of the stack (from top to bottom) after each operator is processed.

      8 6 3 4 + * 2 / 5 3 * - +
      

    3. If the postfix evaluator is given an expression that is not a valid postfix expression, the algorithm will fail to give a correct answer. Give an example of each case where the algorithm might fail and explain why it fails.

PROGRAMMING PROJECT (10 points)

A sparse matrix is a 2-dimensional array where a large portion of the array stores no data. For example, this 5 × 5 integer matrix could be considered sparse assuming we only store positive integers in the matrix:

0 0 0 9 0
0 8 0 0 0
7 0 0 6 0
0 0 0 0 0
0 5 0 0 0

Instead of storing a sparse matrix using a two-dimensional array, we can store this using linked lists where we only store nodes for the locations that have non-zero values. The sparse matrix above would be stored as shown in the picture below:

Assignment

Download the project file SparseMatrix.zip. In this project, you should complete the class SparseMatrix that implements a sparse matrix of integers using linked lists. Each positive value of the matrix is stored using a node that has a field for the data value, fields to store the location of the value in the matrix (row and column), and fields for references to the next node in the same row and same column. Remember that only non-zero values are stored in nodes in the data structure. All "missing" nodes represent locations in the matrix where the data value is 0.

The sparse matrix contains two arrays of references to the heads of the lists of nodes for rows and columns. (See the picture above.)

Programming Requirements

Implement the SparseMatrix class based on the javadoc file SparseMatrix.html and the information below. DO NOT CHANGE ANY CODE ALREADY GIVEN TO YOU.

Helpful Programming Advice

It is much easier to write a little code and debug, repeating many times, than it is to write many lines of code and then debug. If you have partially complete but working program, you will receive more credit, than a complete program that is not working. Therefore, we suggest the following strategy for this assignment:

  1. Start by only considering row links only. Write set to handle non- zero values, getNumRows, getNumColumns, getByRow, and getNumElementsInRows. Write stubs for remaining methods. Develop test cases and test.

  2. Now update set to consider the column links for non-zero elements. Complete getByCol and getNumElementsInColumn. Test.

  3. Update set to handle zero values. Add test cases and test.

  4. Write and test transpose.

As you complete each step, save your work elsewhere. This way, if you really get stuck and run out of time, you can restore a previous version that partially works to maximize your partial credit.

Debugging/Testing

Supplied in your project file is SparseMatrixTester.java which contains a simple program to test the functionality of your data structure. Add comments to the tester to explain what each part is doing. Explain why the try/catch blocks are needed. (Don't say: "because an exception could be thrown". Explain what can go wrong specifically to cause the exception to occur.)

When you run the program, it will ask you to enter a data value, row and column. It will then try to set that row and column in the sparse matrix to the given value. It will then display the matrix by scanning each row first, then again by scanning each column to see if all of your links are correctly maintained. Additionally, it will display a number in square brackets at the end of each row and bottom of each column to tell you how many nodes you have in each list. These numbers should correspond to the number of nonzero values in each list. For example, here is the output after storing the value 2 in row 1 column 0 in a 4 × 3 matrix originally containing only zeroes (user input in italics):

SPARSE MATRIX TESTER
At each prompt, input a triple: data row column
For example, to set row 2 column 1 to the value 43,
you would input 43 2 1
Input -1 -1 -1 to exit input loop.
Once you exit input loop, the transpose will be displayed.
Input number of rows for sparse matrix: 4
Number of rows: 4
Input number of columns for sparse matrix: 3
Number of columns: 3
Sparse Matrix by Rows:
0	0	0	[0]
0	0	0	[0]
0	0	0	[0]
0	0	0	[0]
[0]	[0]	[0]	
Sparse Matrix by Columns:
0	0	0	[0]
0	0	0	[0]
0	0	0	[0]
0	0	0	[0]
[0]	[0]	[0]	

Input: 2 1 0
Storing 2 in row 1 column 0
Sparse Matrix by Rows:
0	0	0	[0]
2	0	0	[1]
0	0	0	[0]
0	0	0	[0]
[1]	[0]	[0]	
Sparse Matrix by Columns:
0	0	0	[0]
2	0	0	[1]
0	0	0	[0]
0	0	0	[0]
[1]	[0]	[0]	

Input: -1 -1 -1

The TRANSPOSE of your matrix is: 
Sparse Matrix by Rows:
0	2	0	0	[1]
0	0	0	0	[0]
0	0	0	0	[0]
[0]	[1]	[0]	[0]	
Sparse Matrix by Columns:
0	2	0	0	[1]
0	0	0	0	[0]
0	0	0	0	[0]
[0]	[1]	[0]	[0]	

The two matrix outputs should always match, but each is generated using different methods of your SparseMatrix class.

TESTING USING THE COMMAND LINE: A way to speed up your testing is to run your program from the command line rather than through Eclipse. (You can still use Eclipse to edit the file.) On the LINUX terminal, open the Terminal application and go to the directory that contains your source code. For example, if your workspace is on your desktop, then you would type:

cd Desktop/MyWorkspace/SparseMatrix/src

If you then type ls, you can list your files in that directory (folder) and you should see the java files. To compile your program, type

javac *.java

If you see compiler errors, then go back and edit your Java file. If you get the OS command prompt back without errors, you should be able to run your program. To run it, type

java SparseMatrixTester

Now, to speed things up, instead of entering each set of data values from the keyboard each time you run the program, you can store all of the inputs in a text file in the same order as you would type them in at the keyboard. For example, for the example above, your data file should look like this:

4
3
2 1 0
-1 -1 -1

Then, when you run the program, you can redirect the data in the file into your program as keyboard input as follows:

java SparseMatrixTester < datafile.txt

This should make debugging faster since you can just examine your output for correctness. If you take 15-211, you will learn a more sophisticated way to test your code using unit testing with JUnit.

You can also cut and paste your data file into the Console area in Eclipse when you run the program.

Documentation & Style

You should add javadoc-style comments to your SparseMatrix class to match the comments given to you in the supplied html file. Make sure you document your code carefully, especially the set method, to explain what you are doing. Use accepted Java programming style throughout your code.

Hand-In Instructions & Late Submissions

Your submitted zip file should include the complete Java program (all Java files). Double-check your zip file before you submit to make sure all of your code is there.

See the course website for instructions on how to hand in your program and the policy for late submissions.