The goal of this assignment is to learn about ArrayList implementations and to practice sorting.
An array list is a data structure that, like an array, stores a list of elements in a given sequence, and provides constant-time access to each element. Unlike an array, an array list grows as needed to accomodate more elements.
This assignment requires you to implement an array list that keeps its contents in sorted order. Your implementation will be somewhat similar to the implementation of a generic array list, except that (a) your code is specialized for strings rather than storing objects of a parametrized type, (b) your code will keep the strings in sorted order, and (c) your array list will not keep any duplicate strings. Your implementation will resemble that of an array list in using an array to store all the contents of the sorted array list, and using an additional integer variable to remember the number of values in the sorted array list.
The contents of the array list must be kept in sorted order, that is, sorting occurs every time a value is added. The sorting algorithm you use is similar to insertion sort, as described in detail below.
Like every array list of size x, the elements of the array lists are stored at indices 0..x-1 of the array, and array.length must be >= x. Whatever (if anything) is stored in locations x..array.length-1 is never accessed by your code, so doesn't matter.
For this assignment, all string comparisons must be case-independent, that is, "edo" equals "Edo" equals "EDO", and all three are greater than "Biagioni", so that "Biagioni" sorts in the list before "Edo", that is, the array will contain { ... , "Biagioni", ..., "Edo", ...}.
For this assignment, you are not allowed to use the ArrayList class in any way, shape or form. You are essentially re-implementing the ArrayList class, and using any variables of type ArrayList or any ArrayList methods would defeat the purpose of the assignment. Likewise, you are not allowed to call any sort method that you have not created yourself. You are not even allowed to use Arrays.copyOf -- to reallocate an array: use new to create the array, then a for loop to copy the elements.
public interface SortedArrayListInterface { // List methods that are useful for a sorted array list int size(); // if the index is not valid, get throws java.lang.IndexOutOfBoundsException String get(int index); // return true if the value has been added, false if it was already present boolean add(String value); // return true if the value has been removed, false if it was not present boolean remove(String value); // return the index at which the string can be found, or -1 if not found // since the array is sorted, indexOf uses binary search int indexOf(String value); // return the contents with blanks (" ") in-between String toString(); }
Note there is no set method, since a call to set might break the invariant that the elements of the SortedArrayList are in sorted order.
Your SortedArrayList class must implement SortedArrayListInterface, and provide the six corresponding methods.
The contents must be stored in an array of String values, declared as String[] data; This array must be an instance variable of the SortedArrayList class.
The SortedArrayList class must also have an integer variable to keep track of the number of strings in the array, which is the size of the sorted array list.
The constructor for SortedArrayList takes no arguments and creates an empty SortedArrayList (size() must return 0), and must initialize the internal array data to have size 1. The add method must increase the size of this array by three every time more space is needed. This means data.length can only be 1, 4, 7, 10, and, more generally, 3i+1 for some i.
For simplicity, the remove method should never reduce the size of the array, so the array can only grow, never shrink.
The add method must insert the value at the correct sorted position in the array. For example, if an array already contains "a" at index 0, "c" at index 1, and "d" at index 2 (meaning that size would return 3), then adding "b" must shift the elements after b out of the way to make room for "b". The resulting final sorted array list will have size 4 and elements "a" at index 0, "b" at index 1, "c" at index 2, and "d" at index 3. This call to add would then return true.
For this sorted array list, the toString method must return the string "a b c d" -- there must be exactly one blank between two successive strings, and no blanks at the beginning or the end of the string. For an empty sorted array list toString must return "", the empty string.
Adding "A" to this sorted array list would return false, since "a" is already in the array, even though one is uppercase and the other is lowercase -- for this assignment, you must compare strings using String.compareToIgnoreCase.
The sorting needed for the add method is similar to the inner loop of insertion sort, and you are welcome to reuse any code from your Sorting assignment.
Essentially, the add method must do the following:
Removing element "a" (or "A") from an array with size 4 and elements "a" at index 0, "b" at index 1, "c" at index 2, and "d" at index 3, would leave the array with "b" at index 0, "c" at index 1, and "d" at index 2, and return true. In contrast, removing "x" would leave the array unchanged and return false. You must figure out the algorithm for removing, which like adding, will require shifting (some of) the elements of the array.
Add to your SortedArrayList class a boolean unitTest() method that tests each of the above methods (the constructor, size, get, add, remove, indexOf, and toString) enough to convince yourself that they work. Each of the methods must be tested with an empty SortedArrayList, a SortedArrayList with one element, and a SortedArrayList with more than one element. The String parameters to the calls must be null, the empty string, and multiple non-empty strings. The index parameter to get must be negative, 0, 1, positive, and larger than the ArrayList. Be sure this unit test catches and verifies the appropriate exception thrown when these methods throw exceptions.
Your unitTest must return true if all the tests pass and false otherwise. Your unitTest method should never throw any exceptions.
Give a clear analysis of the worst-case, best-case, and average-case execution time for each of the add and the remove methods. Each of the 6 analyses must include both a clear explanation, and a result of the form O().
If you have not completed the implementation in part 2, you can still get credit for this section by providing an analysis of your design for the add and remove methods -- be sure to describe your design in sufficient detail that the TA can tell what you are analyzing.
Once you are done, find your src directory and navigate to edu.ics211.h06, then turn the .java files and your analysis.txt into Laulima directly, without zipping or archiving.