We want to extend exercise Adding support to retrieve statistical data. by adding a method
int getMedian(). For this purpose our
current implementation lacks ordering of input values. Consider
the following sample of values:
2, 7, 0, -3, 4
Obtaining the median requires ordering these values:
-3, 0, 2, 4, 7
Thus the given sample's median is 2. Solve this exercise in
the following order:
For testing and other purposes it is convenient to
provide an additional method returning the array of values
being added so far:
/**
* @return The array of values entered so far
*/
public int[] getValues() {
...
return ...;
}
Caution
Do not just return your internal array int[] values! Due to the amortized
doubling implementation this will in most cases contain
unused positions on top of added values.
You may either construct a suitable copy containing
the current elements yourself or get enlightened by reading
the API documentation of copyOfRange(...)
doing your job instead.
Provide some tests to assure your sorting implementation
works well. You'll implement the actual sorting in the next
step. Right now testing for correct sorting will fail (unless
a given set of values had already been added in ascending
order). A test might look like:
final int[]
unsortedValues = {0, -1, 5, 2, 7, 6},
sortedValues = {-1, 0, 2, 5, 6, 7};
IntegerStore store = new IntegerStore();
for (final int i: unsortedValues) {
store.addValue(i);
}
// Now check your store for correctly sorted order of elements
...
Do not forget to consider value sets which include
duplicates and write tests accordingly!
Modify your
addValue(...) method's implementation. Though
there are more elaborate sorting methods available in Java
we'll do it the hard way ourselves here. We intend to insert
new values at the »right« position to always keep the array
sorted. Consider the following sequence:
The addValue(...)
method now provides a sorting compatible position for
inserting. When adding the last value 2 the internal array
already contains the sorted values (1, 3, 7, 9). Traversing
this array shows that the new value of 2 should be inserted
between 1 and 3 and thus at array index 1. The remaining three
values 3,7 and 9 each have to be shifted one position to the
right.
This way our sequence of values always remains
sorted.
Provide a constructor public
IntegerStore(final int[] values) in a meaningful way
with respect to median calculations.
Provide some tests both for even and uneven sample
sizes. All of these will probably fail till you complete your
implementation.
Finally complete the desired double getMedian() method's
implementation and actually test it. Returning a meaningful
result requires at least one element:
/**
* <dl>
* <dt><b>Precondition:</b></dt>
* <dd>There must be at least one element.</dd>
* </dl>
*
* @return The sample's median.
*/
public double getMedian() {
...
return ... ;
}
Implement a main method as in Reading console input asking the user for an
arbitrary number of values. Then compute both their average
and median like:
How big is your sample? 5
Enter value #1 of 5: 1
Enter value #2 of 5: -2
Enter value #3 of 5: 1
Enter value #4 of 5: 5
Enter value #5 of 5: 2
Your sample's average is: 1.4
Your sample's median is: 1.0
The copyOfRange(...)
method in getValues()
returns that portion of our int[]
values array actually been filled with data.
Provide some tests assuring your sorting implementation
works well prior to actually implementing the actual sorting
in the next step. Right now testing for correct sorting will
fail (unless a given set of values had already been added in
ascending order). A test might look like:
final int[]
unsortedValues = {0, -1, 5, 2, 7, 6},
sortedValues = {-1, 0, 2, 5, 6, 7};
IntegerStore store = new IntegerStore();
for (final int i: unsortedValues) {
store.addValue(i);
}
// Now check your store for correctly sorted order of elements
...
Do not forget to consider value sets which include
duplicates and write tests accordingly!
Modify your
addValue(...) method's implementation. Though
there are more elaborate sorting methods available in Java
we'll do it the hard way ourselves in this exercise. Consider
the following example:
Prior to inserting a new value our addValue(...)
method shall find a suitable position inside the array of
already added values to insert the new value. When adding the
last value 3 in the above example the internal array already
contains the values (1, 2, 7, 9). Traversing this array shows
that the new value of 3 should be inserted between 2 and
7.
Thus a general strategy inserting a new value candidate
might be:
Find the first index pointing to an existing value
being larger or equal to the given candidate. In the above
example this index value is 2 pointing to value 7.
If there is no such existing value just add the new
value at the array's top as you did without bothering
about sorting.
Shift the “right” part of the array
starting at index 2 in our example one position to the
right thus creating a free (denoted by “F”)
insert position:
You may now insert your latest value 3 at the free
index position 2 ending up with a well sorted array (1, 2,
3, 7, 9).
This example just illustrates a (very simple!)
sorting algorithm.
Hint: On implementation be very careful with respect
to “off by one” errors you are likely to
encounter. The tests you have written beforehand will
guide you.