15-100 Lecture 23 (Monday, March 21, 2004)
Remove

Assume we have a nice ordered array. That means it has no "holes" in it and it's ordered. Now let's remove an item from it. When we remove an item we want to cover up the hole we just made by shifting everything behind it forward by one. But why do we want to do all of that work to avoid introducing holes?

Let's first consider what would happen if we didn't cover up the hole. The code would look like this:

``````
public void removeNth (int n){
names[n] = null;
count --;
}
``````

Well first off those holes would mess up our insert code. An ordered inserting method would throw a NullPointerException when it tries to compare the object to insert with the null value our hole leaves. Even a simple insert at end method would be messed up. The insert would overwrite a place in the array because when holes are introduced but count is decreased, count would keep track of how many items were in the array and not the positions they were in.

So now let's write the code that fills in the hole:

``````
public void removeNth (int n){
names[n] = null;
for (int i = n; i < (count-1); i++){
names[i] = names[i+1];
names[i+1] = null;
}
count --;
}
``````

Now let's remove a specific name. We first have to find where the name is stored in the array before we can delete it. So write a binarySearch helper method to find the index of where the name is stored.

``````
public int binarySearch (String name) throws NameNotFoundException{
int left = 0;
int right = names.length - 1;
int pivot = (left + (right - left)/2);

while (right >= left) {
int difference = names[pivot].compareTo(name);

if (difference == 0)
return pivot;
if (difference > 0)
right = pivot - 1;
if (difference > 0)
left = pivot + 1;

pivot = (left + (right - left)/2);
}

throw new NameNotFoundException("Name " + name + " was not in the array");
}

//make sure we have written the code for NameNotFoundException so we can throw it
public class NameNotFoundException Extends Exception {
public NameNotFoundException (String msg){
super(msg);
}
}

//now we can write our removeName by calling on our two methods
public void removeName (String name) {
int index = binarySearch(name);
removeNth(index);
}
``````
Filtering

Want to take a name parameter and return a sub-array (still in order) of all names in the first array that are greater than the name parameter.

Can do this in two ways: 1) start at the beginning and skip those who don't satisfy, find the first name that satisfies criteria then copy the list till reach the end; or 2) we can start at the end and move backward and copy until we reach the first one that doesn't satisfy the criteria and then exit the search.

The backwards and copy method works the best if you don't have to maintain order. However, to keep the order as we copy we would have to use the forward copying method.

Note that we can cut down on the amount of time we spend searching for the index to start copying at if we modify our binary search so that it doesn't throw an exception and instead always returns an index. The index that the binary search returns is either equal to name or roughly where in the array we would expect it to appear (it would be off by + or - 1).

``````public SortedNames getGreaterThan (String name) {
//to be done tomorrow (along with modification of the binary search)
}
``````