Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic binary search Java

Tags:

java

I've been trying to make this code work. I have to create a generic binary version of the binary search. I'm not sure how to compare two generic types without the comparable interface

import java.util.ArrayList; 

public class BinarySearcher<T> {
    private T[] a;

    public BinarySearcher(T[] words) {
        a = words;
    }

    public int search(T v) {
        int low = 0;
        int high = a.length - 1;
        while (low <= high) {
            int mid = (low + high) / 2;
            T midVal = a[mid];  

            if (v.compareTo(midVal) < 0) {
                low = mid - 1;
            }   

            else if (v.compareTo(midVal) > 0) {
                high = mid  + 1; 
            }
        }

        return -1;
    }

    public int compareTo(T a) {
        return this.value.compare - b;
    }
}

This is the tester class:

import java.util.Arrays;
import java.util.Scanner;
/**
  This program tests the binary search algorithm.
*/
public class BinarySearchTester {
    public static void main(String[] args) {
        String[] words = {"Alpha", "Bravo", "Charlie", "Delta", "Echo", 
            "Foxtrot", "Golf", "Hotel", "India", "Juliet", "Kilo", "Lima", 
            "Mike", "November", "Oscar", "Papa", "Quebec", "Romeo", 
            "Sierra", "Tango", "Uniform", "Victor", "Whiskey", "X-Ray", 
            "Yankee", "Zulu"};
        BinarySearcher<String> searcher = new BinarySearcher<String>(words);
        System.out.println(searcher.search("November"));
        System.out.println("Expected: 13");
        System.out.println(searcher.search("October"));
        System.out.println("Expected: -1");
    }
}
like image 601
carlly Avatar asked Mar 24 '11 22:03

carlly


3 Answers

public class BinarySearcher<T extends Comparable<T>> { ...

This'll allow your BinarySearcher to work for everything that can be compared with compareTo, which should be generic enough.

like image 155
Erik Avatar answered Oct 04 '22 00:10

Erik


There's no way that your generic method can compare two instances of some arbitrary type T, without having any constraints on T or having information some other way about how to compare two Ts.

You have a few choices:

Add a constraint to T:

public class BinarySearcher<T extends Comparable<T>>

Or pass in a Comparator<T> to your search method that can be called to do the comparison:

public int search(T v, Comparator<T> comp) {
    // ...
    if (comp.compare(v, midVal < 0)) {
    // ...
}

Side note: I would avoid calling compareTo two times in your search method; you don't know if comparing the two objects is expensive. Instead of this:

if (v.compareTo(midVal) < 0) {
    low = mid - 1;
}   
else if (v.compareTo(midVal) > 0) {
    high = mid  + 1; 
}

Do something like this:

int result = v.compareTo(midVal);
if (result < 0) {
    low = mid - 1;
}   
else if (result > 0) {
    high = mid  + 1; 
}
like image 21
Jesper Avatar answered Oct 04 '22 01:10

Jesper


Even after doing all the changes suggested above, the Conditions you are using are incorrect (your changing of low and high pointers) and you need an else clause after else if to return the index.

public class BinarySearcher<T extends Comparable<T>> {
    private T[] a;

    public BinarySearcher(T[] words) {
        a = words;
    }

    public int search(Comparable<T> v) {
        int low = 0;
        int high = a.length - 1;

        while (low <= high) {
            int mid = (low + high) / 2;
            T midVal = a[mid];
            int result = v.compareTo(midVal);

            if (result < 0) {
                high = mid - 1;
            }

            else if (result > 0) {
                low = mid + 1;
            } 

            else {
                return mid;
            }
        }

        return -1;
    }
}
like image 20
o12 Avatar answered Oct 04 '22 00:10

o12