Return to lecture notes index
15-100 Lecture 24 (Wednesday March 23, 2004)

The class that was used today is here. Additionally, the tests taken last friday were returned in class. If you didn't get your test go to Kesden's office hours and you can pick it up there.
Filtering ... continued
Last class we started going over what filtering was, but we didn't finish writing some code for actual filter methods. Today we'll finish up talking about filter methods by writing code for the two types that we talked about last class, and then discussing and coding up a third version.

First Version

The first version of a filter method that we talked about last class was a filter method that started at the begining and moved toward the end of the list. So we have the general idea of this methods, we're just going to have to add some specifics about how exactly this method is going to work. So we already know two things about the method that we're going to write. Its going to walk through the list that we have, position by position, and that its going to start at the begining of the previous list. Now, we just have to decide what the method's doing at each position. In order to do this we have to make a couple more decisions about how we want the filter method to work, namely whether we want the elements that are greater or less then the given element. In this case we'll take the elements that are greater then the given element. Since this is the case we'll check the element at each position and if it's greater then the given element we'll add it to the list. Now its time to code. // remember to talk about time to write start at end/begin


/*
This class filters the array holding the names, and 
returns a new SortedNames holding only names greater then the
name passed in
*/
   public SortedNames getGreaterThanForward (String name){

        //creates the new SortedNames, which the names  
        //that satisfy the filter will be added to
        SortedNames bigNames = new SortedNames(name.length);

        //goes through each position in the array
        for(int index = 0; index < count index ++){

          //if current position passes filter criteria
         //adds it to the list
          if(names[index].compareTo(name)>0){
	     bigNames.insert(names[index]);
	  }
	}

        //returns the list of names that was created
	return bignames;
   }

While we're thinking about this method, what changes would we have to make to the method above if we decided to filter for the names that were less then the given name, instead of greater then?

Because of the way that our class is set up the only thing that we would have to change is to the if statement inside the for loop. Change "if(names[index].compareTo(name)>0)" to "if(names[index].compareTo(name)<0)" and you'll switch the filter.

Second Version of the Filter

In the second version of a filter method we're going to start at the end of the array and work our way forward. Think of what types of changes we might have to make to the method that we previously wrote, if we make this change. Looking over the method, it turns out that the only change that we'll have to make is in the for loop. So a filter method that starts at the end of the list and works its way forward would look like the method below.


/*
This class filters the array holding the names, and
returns a new SortedNames holding only names greater then the
name passed in
*/
   public SortedNames getGreaterThanReverse (String name){

        //creates the new SortedNames, which the names
        //that satisfy the filter will be added to
        SortedNames bigNames = new SortedNames(name.length);

        //goes through each position in the array
        //!!only change in the method is on the line below!! 
        for(int index = (count -1); index >= 0; index --){

          //if current position passes filter criteria
         //adds it to the list
          if(names[index].compareTo(name)>0){
             bigNames.insert(names[index]);
          }
        }

        //returns the list of names that was created
        return bignames;
   }

Now we've done these two types of the method, and they look pretty similar. So when would you want to use one or the other? Well when thinking about this question we want to think about what might speed up our program, and get it to run more efficiently. One of the areas that can give us a quicker program is if we add the elements to the new list already in the correct order. That way we don't have to shuffle the elements around each time we want to add a new one. In order to do this we would want to add the smallest elements to our list first, so this would imply that of these two searches the getGreaterThanForward will probably be the faster seach. Another area that would give us some speed up comes from the fact that the list is ordered. Since it is ordered if we were looking for items only smaller then a given item, and working backwards, or we were looking for items only larger then a certain item and working forwards we could stop looking at the first item that didn't meet the criteria. There are two things to be careful about here though. The first is the most important and it is that the reverse cases, looking for the larger items and starting from the frount, or looking for smaller items and starting from the rear don't work. This is because in those cases the invalid elements come before the valid ones, instead of the other way around. The other thing to be careful of, is that if you're starting from the back, and adding to many elements to the new array you're going to lose more time by shifting elements when adding them then you're going to gain from being able to stop at some point(see the above paragraph).

Third Version of the Filter

The third version of the filter is going to work very differently from the first two versions. This version is going to involve some binary searching. If you need to review binary search look at Lecture 24 where its first introduced.

In this version we're going to deal with the problem of sometimes having to look at a whole bunch of items that we don't want. Instead of doing that we'll write a filter method that uses a binary search like method to find the approximate position of where the elements we want start. That way we can then write our filter method, starting from that position.

What does using the binary search like method to find our starting position get us? Since binary search works a lot more efficiently then just going through the items one by one we'll have to look at a lot fewer of the items that we don't want to add to our list. This in turn will allow our method to run faster then it might have otherwise.

In order to write this method however, we're going tohave to write our binary search like method first. In this case we'll call it getIndexNear.


/*
works like a binary search
returns a location that is approximately where we want it
although it might be one less then where it actually starts
*/
  private int getIndexNear (String name) { 
    int left = 0;   //lower index
    int right = count-1; //upper index
    int pivot = left + (right-left)/2; 
 
 
    while (right>=left) { 
      //finds the value to do the binary search 
      //comparisons on
      int difference = names[pivot].compareTo(name); 
 
       //we have found the value equal to the value
      //passed in, returns the location
      if (difference == 0) 
        return pivot; 
 
       //case where new pivot is greater then value
       //passed in
      if (difference > 0) { 
        right = pivot-1; //updates upper index
      } 
 
       //case where new pivot is less then value
       //passed in
      if (difference < 0) { 
         left=pivot+1;  //updates lower index
      } 
 
      //updates pivot since one of the
      //indexes have been updated
      pivot = left + (right-left)/2;  
 
    } 
 
    return pivot; //returns the location
  } 

Since we have finished that we can now go on to writing the filter method. Once the binary search like method is done writing the rest of this filter is a lot like writing the two previous filters.


/*
Filter method
returns a SortedNames that only contains the elements 
of the origonal list that were greater then the 
input value

Uses binary search to improve its run time
*/
public Sortednames getGreaterThanBinary (string name){
  
  //creates the new SortedNames, that the names that
  //satisfy the filter will be added to 
  SortedNames bigNames = new SortedNames(names.length();

  //uses the binary search like method to find the index
  //about where the values that we want start
  int goodStartingPlace = getIndexNear(name);

  //iterates through the array adding the values to the new
  //SortedNames, starting from the position that we just found
  for(int index = goodStartingPlace; index < count; index++){
    
    //current name satisfies the criteria
    if(names[index].compareTo(name) > 0 { 
      bigName.insert(names[index]); //adds the name to the list
  }
}
return bigNames;
}