Download Programming Assignment 1 - University of Washington

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Array data structure wikipedia , lookup

Linked list wikipedia , lookup

Java ConcurrentMap wikipedia , lookup

Transcript
University of Washington, Tacoma
TCSS 342, Autumn 2004, Section A
Programming Assignment 1 (Linked List Implementation with Iterator)
Assigned: Thursday, October 14, 2004
Due: Thursday, October 21, 3:00pm
This programming assignment focuses on implementation and efficiency of linked lists and list iterators. This
is an individual assignment. It should be turned in online through the course webpage e-submit system.
For this program, you will be given an incomplete class MyLinkedList; it is a doubly-linked list with
dummy header and tail. It resides in file MyLinkedList.java that contains an almost-complete
implementation of the interface java.util.List. This file, along with a testing class, can be downloaded
from the course web page. (You should perform your own testing and should not assume that the provided test
file is exhaustive.)
Your assignment is to complete the implementation as specified below, as well as making a few performanceincreasing optimizations to the MyLinkedList class. A major part of this assignment will be writing a class
that represents a birectional list iterator, and using it to implement missing methods from your list.
The following methods are already defined for you, with behavior as described in the relevant Java API for the
List interface (which can be found at http://java.sun.com/j2se/1.4.2/docs/api/java/util/List.html):




















public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
MyLinkedList()
void add(int index, Object element)
boolean add(Object element)
void addFirst(Object element)
void addLast(Object element)
void clear()
boolean contains(Object element)
Object get(int index)
int indexOf(Object element)
boolean isEmpty()
int lastIndexOf(Object element)
Object remove(int index)
boolean remove(Object element)
boolean removeAll(Collection c)
Object set(int index, Object value)
int size()
List subList(int startIndex, int endIndex)
Object[] toArray()
Object[] toArray(Object[] array)
String toString()
You must make the following modifications to the MyLinkedList:
(not supported)
1. Implement a ListIterator for the MyLinkedList.
To implement the listIterator , listIterator(int), and other methods and several other portions
of the code for this program, you must write a class that implements the java.util.ListIterator
interface. The relevant Java documentation for this interface is available at
http://java.sun.com/j2se/1.4.2/docs/api/java/util/ListIterator.html.
Implement your list iterator as an inner class inside the MyLinkedList class, so that it has access to the fields
and methods of the MyLinkedList object that created it. Your list iterator should only allocate a fixed
amount of storage; it may not contain, for example, an array of all the elements in the list. Please put brief
comments on your iterator class and its methods. You do not need to use Javadoc-style comments.
The ListIterator interface has the following methods. All methods of your list iterator class except its
constructor must run in O(1) time.

public YourClassName(int index)
Constructs your list iterator such that the first element that will be returned by a call to next will be the element
at the given index, and a call to the iterator's nextIndex method would return the value index. This
constructor is not part of the java.util.ListIterator interface but is recommended.

public void add(Object element)
Inserts the specified element into the list. The element is inserted immediately before the next element that would
be returned by next, if any, and immediately after the next element that would be returned by previous, if
any. (If the list contains no elements, the new element becomes the sole element on the list.)
The new element is inserted before the implicit cursor: a subsequent call to next would be unaffected. (This call
also increases by 1 the value that would be returned by a call to nextIndex.)

public boolean hasNext()
Returns true if this list iterator has more elements remaining. (In other words, returns true if a call to next
would return an element rather than throwing an exception.)

public Object next()
Returns the next element in the list, and advances the iterator's position by one element. This is the element
whose index would currently be returned by nextIndex(), as well as the element that would be returned by a
call to get(nextIndex()) on the list itself. This method may be called repeatedly to iterate through the list in
a forward direction and return each element of it in forward order.
Your implementation should throw a NoSuchElementException if the iterator has already finished iterating
over all elements of the list.

public int nextIndex()
Returns the index of the element that would be returned by a subsequent call to next. This value is always one
more than the value that would be returned by previousIndex. Returns the list's size if the list iterator is at
the end of the list. Note that calling this method should not actually change the iterator's position.
For example, calling listIterator(0).nextIndex() on any list would return the value 0.

public boolean hasPrevious()
Returns true if this list iterator has elements remaining behind it. (In other words, returns true if a call to
previous would return an element rather than throwing an exception.)

public Object previous()
Returns the previous element in the list, and decreases the iterator's position by one element. This is the element
whose index would currently be returned by previousIndex(), as well as the element that would be returned
by a call to get(previousIndex()) on the list itself. This method may be called repeatedly to iterate
through the list in a reverse direction and return each element of it in reverse order.
Your implementation should throw a NoSuchElementException if the iterator is at the beginning of the list.

public int previousIndex()
Returns the index of the element that would be returned by a subsequent call to previous. This value is always
one less than the value that would be returned by nextIndex. Returns -1 if the list iterator is at the beginning of
the list. Note that calling this method should not actually change the iterator's position.
For example, calling listIterator(0).previousIndex() on any list would return the value -1.

public void remove()
Removes from the list the last element that was returned by next. You do not need to support the ability to call
remove more than once per call to next (that is, you only need to have the ability to remove the last element
seen). You also do not need to support removal if your iterator's add method has been called since the last call to
next. Signify unsupported removal states by throwing an IllegalStateException.

public void set(Object element)
Replaces the last element returned by next with the specified element (optional operation). You do not need to
support the ability to call set after either remove or add have been called on your iterator after the last call to
next.
After successfully implementing your list iterator, you should then use it to improve the runtime of the methods
described previously. To get an example of how an iterator can be used to write methods such as retainAll,
look at the provided version of removeAll as an example.
If you want to compare your class's behavior against what is expected, try substituting a
java.util.LinkedList for your MyLinkedList in the testing code and re-running it.
If you have trouble successfully implementing the iterator, a quick hack to get a ListIterator is the
following:
ListIterator itr = Arrays.asList(this.toArray()).listIterator();
The code above copies the elements of your MyLinkedList into a temporary second List, and returns a list
iterator for this second list. It will work for read-only operations but not for removals or other modifications,
because it would modify the second list and not your own. Using hacks like the above are considered
unacceptable for this assignment because of their unnecessarily slow runtime (the line above is O(n) because it
must copy all the elements of your list.)
In general if there is a method that you do not wish to implement right away, right its header and throw an
UnsupportedOperationException inside. This will allow your code to compile so that you can test
incrementally.
2. Implement the following list of methods, to complete the implementation of java.util.List. For the
methods that take a Collection c as an argument, You may assume that this != c, that c != null,
and that neither collection will be modified during the execution of your code. Unless specified otherwise, each
method should run in O(1) time.

public boolean addAll(Collection c)
Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by
the specified collection's iterator. Returns true if this list changed as a result of the call. This will always be
true if c has any elements inside it.
Your implementation's runtime should be O(n) where n = c.size().

public boolean addAll(int index, Collection c)
Inserts all of the elements in the specified collection into this list, starting at the specified position. Shifts the
element currently at that position (if any) and any subsequent elements to the right (increases their indices). The
new elements will appear in the list in the order that they are returned by the specified collection's iterator.
Returns true if this list changed as a result of the call. This will always be true if c has any elements inside it.
Your implementation's runtime should be O(n) where n = index + c.size(). (That is, the runtime should
be proportional to the time necessary to advance through your list to the given index, plus the number of elements
from c to be added.)

public boolean containsAll(Collection c)
Returns true if this collection contains all of the elements in the specified collection. Your implementation
should iterate over the specified collection c, checking each element returned by the iterator in turn to see if it is
contained in this list. If all elements are contained, true is returned, otherwise false.
Your implementation's runtime should be O(mn) where m = c.size() and n = this.size(). (That is, the
runtime should be proportional to the time necessary to search through your list for each element in c.)

public Iterator iterator()
Returns an iterator over the elements in this list (in proper sequence).
Your implementation should merely return a list iterator over the list that begins at index 0.

public ListIterator listIterator()
Returns an iterator of the elements in this list (in proper sequence). This operation is the same as creating a list
iterator at index 0.

public ListIterator listIterator(int index)
Returns a list iterator of the elements in this list (in proper sequence), starting at the specified position in this list.
The specified index indicates the first element that would be returned by an initial call to the iterator's next
method.
Your implementation's runtime should be O(n) where n = index.

public boolean retainAll(Collection c)
Retains only the elements in this list that are contained in the specified collection. In other words, removes from
this list all of its elements that are not contained in the specified collection. Your implementation should iterate
over this list, checking each element returned by the iterator in turn to see if it is contained in the specified
collection. If it is not contained, it is removed from this list with the iterator's remove method. Returns true if
this list changed as a result of the call.
Your implementation's runtime should be O(mn) where m = c.size() and n = this.size(). (That is, the
runtime should be proportional to the time necessary to search through your list to find and remove each element
contained in c.)
3. Make modifications to some of the existing methods of the MyLinkedList class to improve their runtime
efficiency, as follows:
The current implementation of several methods unnecessarily have slow runtime for large-size lists, because
they repeatedly call the get method, which is O(n) for n = size(). Modify the following methods so that
they complete in the faster time specified, with the correct result. In many cases, the best way to make these
modifications is to use your list iterator within your MyLinkedList class's methods. You will be graded both
on successfully reducing your runtime and on using the ListIterator to do so when appropriate. These are
the methods to modify:

public int indexOf(Object element)
The current implementation of this method is O(n2), where n = size(). Improve this method's
runtime to O(n).

public int lastIndexOf(Object element)
The current implementation of this method is O(n2), where n = size(). Improve this method's
runtime to O(n). Also, change this method to take advantage of the doubly-linked structure of the list.
Currently, lastIndex iterates forward starting from the beginning of the list. A better algorithm is to
iterate backwards, starting from the end of the list; this way, you can stop iterating as soon as a
matching element is found.

public Object[] toArray(Object[] array)
The current implementation of this method is O(n2), where n = size(). Improve this method's
runtime to O(n).

public String toString()
The current implementation of this method is O(n2), where n = size(). Improve this method's
runtime to O(n).
Submission and Grading:
Submit this assignment online, as with all programming assignments, via the link on the course web site. Turn
in your MyLinkedList.java only.
The correctness of your program will be graded on matching the expected behavior of the methods to be
implemented. To get a good idea of the expected behavior, run testing code on a java.util.LinkedList
and then substitute your MyLinkedList, and look for differences. Exceptions should not occur under normal
usage except as specified previously.
The style and design of your program will be graded on whether you follow the program specification above,
whether you implement the interfaces given, the reasonableness of your list algorithms, obeying the Big-Oh
runtime requested for each method, the presence of reasonable brief comments in your source code (a short
header on each file, each method, and on particularly complex code sections), the use of meaningful identifier
names, avoiding redundancy, and general spacing and indentation of your code.
This program must be completed individually. It is subject to the plagiarism and conduct rules specified in the
course syllabus. You should not look at complete source code for classes that implement List or
ListIterator except as shown in the textbook; this includes looking at the Sun Java source code for these
classes. If you get help from friends, classmates, books or websites, please cite this in comments in your code.