15-100 Lecture 22 (Wednesday, March 16, 2004)
Building off of Monday's Names
Here is a brute force search. We are go through ALL of the array and for each value we look for a match. (If we have an unordered array this is the best search that we can do):
``````
public boolean contains (String name){
for (int index = 0; index < count; index++){
if (names[index].compareTo(name)==0){
return true;
}
}

return false;
}

``````
However we have an ordered array, so we can do better. If we know that the array is ordered we can stop searching as soon as we get to a .compareTo() value that is too large. So let's rewrite contains():
``````
public boolean contains (String name){
for (int index = 0; index < count; index++){
int differance = names[index].compareTo(name)
if(differance == 0){
return true;
}

if (differance >0){ //know that we have gone too far so now can disapoint people much faster
return false;
}
}
//if we exit loop we know the value isn't there
return false;
}
``````
However we can still do better. How about eliminating half of the array for each comparison? If you start in the middle of the array each time (where each time you shink the "to search" array by half to include only the possible values) you will get to your answer much faster. Here's some examples:
``````
a c e g h j l p q r (looking for d)
//Compare d to j (must be in front of j)
a c e g h       //excluded: j l p q r
//Compare d to e (must be in front of e)
a c             //excluded:e g h     j l p q r
//Compare d to c (must be at 0 or not in list)
a               //excluded:c         e g h       j l p q r
//Compare d to a (now know not in array)

c e g h j l p q r (looking for q)
//Compare q to j (must be behind j)
j l p q r      //excluded: a c e g h
//Compare q to p (must be behind p)
q r            //excluded: a c e g h       j l p
//Compare q to r (must be in front of r)
q              //excluded: a c e g h       j l p    r
//Compare q to q (we found it!)
``````
This is called a binary search. Each time you are shrinking your searchable array be half:
64 => 32 => 16 => 8 => 4 => 2 => 1(found it!)
so that's how many searches?
``````
|  Rewritten |             |
|  in powers | Power in    | Number of
N  |  of 2      | terms of N  | comparisons
------+------------+-------------+-------------
64 |  2^6       | 6=log2(64)  | 7
32 |  2^6       | 5=log2(32)  | 6
16 |  2^6       | 4=log2(16)  | 5
8  |  2^6       | 3=log2(8)   | 4
4  |  2^6       | 2=log2(4)   | 3
2  |  2^6       | 1=log2(2)   | 2
1  |  2^6       | 0=log2(1)   | 1
``````
So for a sorted array of N items...How many times will we need to call compareTo, in the worst case? log2(N) + 1

The code for a binary search:

``````

public boolean binarySearch (String name){
int left = 0;
int right = count-1;
int pivot = left + (right-left)/2;

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

if (differance == 0){
return true;
}

if (differance > 0) {
//go left
//left value stays the same
right = pivot - 1; //can exclued the pivot point
}
else {
//go right
//right stays same
left = pivot + 1;
}

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

//if exit loop then know that the searched for value isn't there
return false;
}
``````
Reversing Arrays
NOTE: This breaks binary search (The comparisons are now being done backwards. To correct this you would have to change the code of the binary search).

Example of swapping:

``````
have array: 1 2 3 4 5
//Swap 1 and 5
5 2 3 4 1
//Swap 2 and 4
5 4 3 2 1
//You are done since you don't need to swap 3 with itself
``````
So you swap until you reach middle of set. Let's write the reverse() code:
``````
public void reverse(){
for (int offset = 0; offset < (count/2); offset++) {
swap( offset, (count-1)-offset);
}
}
``````