通用二进制搜索Java

通用二进制搜索Java,java,Java,我一直在努力使这个代码工作。我必须创建二进制搜索的通用二进制版本。如果没有可比较的接口,我不知道如何比较两个泛型类型 import java.util.ArrayList; public class BinarySearcher<T> { private T[] a; public BinarySearcher(T[] words) { a = words; } public int search(T v) {

我一直在努力使这个代码工作。我必须创建二进制搜索的通用二进制版本。如果没有可比较的接口,我不知道如何比较两个泛型类型

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;
    }
}
import java.util.ArrayList;
公共类二进制搜索器{
私人T[]a;
公共二进制搜索器(T[]字){
a=文字;
}
公共整数搜索(TV){
int低=0;
int高=a.长度-1;
while(低0){
高=中+1;
}
}
返回-1;
}
公共整数比较(TA){
返回此.value.compare-b;
}
}
这是tester类:

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");
    }
}
导入java.util.array;
导入java.util.Scanner;
/**
这个程序测试二进制搜索算法。
*/
公共类二进制搜索测试器{
公共静态void main(字符串[]args){
String[]words={“Alpha”、“Bravo”、“Charlie”、“Delta”、“Echo”,
“狐步舞”、“高尔夫”、“酒店”、“印度”、“朱丽叶”、“基洛”、“利马”,
“迈克”、“十一月”、“奥斯卡”、“爸爸”、“魁北克”、“罗密欧”,
“塞拉”、“探戈”、“制服”、“维克多”、“威士忌”、“X光”,
“扬基”,“祖鲁”};
BinarySearcher search=新的BinarySearcher(单词);
System.out.println(searcher.search(“11月”);
System.out.println(“预期:13”);
System.out.println(searcher.search(“十月”);
系统输出打印项次(“预期:-1”);
}
}

公共类二进制搜索程序{…


这将允许您的BinarySearcher处理可以与
compareTo
进行比较的所有内容,这应该足够通用。

不可能比较未实现
Comparable
接口的类型。而不是使用
compareTo()

如果对
T
没有任何约束,或者没有关于如何比较两个
T
的其他方式的信息,您的泛型方法就无法比较某个任意类型的两个实例
T

您有几个选择:

将约束添加到
T

public class BinarySearcher<T extends Comparable<T>>
旁注:在
search
方法中,我会避免调用
compareTo
两次;您不知道比较这两个对象是否昂贵。而不是这样:

if (v.compareTo(midVal) < 0) {
    low = mid - 1;
}   
else if (v.compareTo(midVal) > 0) {
    high = mid  + 1; 
}
if(v.compareTo(midVal)<0){
低=中-1;
}   
如果(v.compareTo(midVal)>0,则为其他情况{
高=中+1;
}
这样做:

int result = v.compareTo(midVal);
if (result < 0) {
    low = mid - 1;
}   
else if (result > 0) {
    high = mid  + 1; 
}
int result=v.compareTo(midVal);
如果(结果<0){
低=中-1;
}   
否则,如果(结果>0){
高=中+1;
}
试试这个:

class BinarySearcher<T extends Comparable<T>>
类二进制搜索器

@Erik的回答显示了如何修改代码,以使参数类型
T
具有可比性

另一种选择是使用比较器,例如

import java.util.ArrayList; 

public class BinarySearcher<T> {

    private T[] a;
    private Comparator<T> c;

    public BinarySearcher(T[] words, Comparator<T> comparator) {
        a = words;
        c = comparator;
    }

    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 (c.compare(v, midVal) < 0) {
                low = mid - 1;
            }   
            else if (c.compare(v, midVal) > 0) {
                high = mid  + 1; 
            }
        }
        return -1;
    }
}
import java.util.ArrayList;
公共类二进制搜索器{
私人T[]a;
专用比较器c;
公共二进制搜索器(T[]字,比较器){
a=文字;
c=比较器;
}
公共整数搜索(TV){
int低=0;
int高=a.长度-1;
while(低0){
高=中+1;
}
}
返回-1;
}
}
您可以通过修改原始构造函数来组合这两种方法,以使用一个比较器,该比较器将要比较的第一个值转换为
Comparable
实例。这可能会进行不安全的转换,如果与T对应的实际类型实际上不是可比的,则会导致
ClassCastException



从设计的角度来看,如果
BinarySearcher
构造函数检查
words
是否已排序,或者对数组本身进行排序,这将是一个更好的主意。如果
单词的顺序不正确,二进制搜索将给出错误的答案。

正如前面提到的其他方法一样,leting T extends Comparable将解决您的问题。你为什么要重新发明轮子?您可以轻松使用现有的通用Java二进制搜索:

System.out.println(Arrays.binarySearch(words, "November", null));
注意,如果null作为可比较参数传递,则采用自然元素顺序


享受吧

即使在执行了上面建议的所有更改之后,您使用的条件仍然不正确(您更改了低位和高位指针),并且如果要返回索引,您需要在else之后使用else子句

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;
    }
}
公共类二进制搜索器{
私人T[]a;
公共二进制搜索器(T[]字){
a=文字;
}
公共整数搜索(可比v){
int低=0;
int高=a.长度-1;
while(低0){
低=中+1;
} 
否则{
中途返回;
}
}
返回-1;
}
}

以下类可用于对任何数据类型进行二进制搜索

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class GenericBinarySearch{

    private int midPoint(int iMin, int iMax){
        return iMin + (iMax - iMin)/2;
    }

    public <T> int search(List<T> list, T Key, int iMin, int iMax, Comparator<T> comparator){
        if(list == null || list.size() == 0){
            return -1;
        }
        int iMid = midPoint(iMin, iMax);
        if(iMid > iMax || iMid < iMin){
            return -1;
        }
        if(comparator.compare(list.get(iMid), Key) > 0){
            return search(list, Key, iMin, iMid-1, comparator);
        }else if(comparator.compare(list.get(iMid), Key) < 0){
            return search(list, Key, iMid+1, iMax, comparator);
        }else{
            return iMid;
        }
    }

    public static void main(String[] args) {
        GenericBinarySearch bs = new GenericBinarySearch();
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);

        int key = 2;
        int iMin = 0;
        int iMax = list.size()-1;

        //Java 8 - Lambda expressions 
        // new Comparator( public T int compare(T o1, T o2) {
        //      return o1.compareTo(o2);
        // }) ---> same expression is replaced by 
        // (T o1, T o2) -> o1.compareTo(o2) or (o1,o2) -> o1.compareTo(o2)   
        int index = bs.search(list, key, iMin, iMax, (o1,o2) -> o1.compareTo(o2));
        System.out.println(index);
    }


}
import java.util.ArrayList;
导入java.util.Comparator;
导入java.util.List;
公共类GenericBinarySearch{
专用int中点(int iMin,int iMax){
返回iMin+(iMax-iMin)/2;
}
公共整数搜索(列表列表、T键、整数iMin、整数iMax、比较器){
if(list==null | | list.size()==0){
返回-1;
}
int iMid=中点(iMin,iMax);
if(iMid>iMax | | iMid0){
返回搜索(列表、键、iMin、iMid-1、比较器);
}else if(comparator.compare(list.get(iMid),Key)<0){
返回搜索(列表、键、iMid+1、iMax、比较器);
}否则{
返回iMid;
}
}
公共静态void main(字符串[]args){
GenericBinarySearch bs=新建GenericBinarySearch();
列表=新的ArrayList();
增加第(1)款;
增加(2);
增加(3);
增加(4);
增加(5);
int键=2;
int-iMin=0;
在里面
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class GenericBinarySearch{

    private int midPoint(int iMin, int iMax){
        return iMin + (iMax - iMin)/2;
    }

    public <T> int search(List<T> list, T Key, int iMin, int iMax, Comparator<T> comparator){
        if(list == null || list.size() == 0){
            return -1;
        }
        int iMid = midPoint(iMin, iMax);
        if(iMid > iMax || iMid < iMin){
            return -1;
        }
        if(comparator.compare(list.get(iMid), Key) > 0){
            return search(list, Key, iMin, iMid-1, comparator);
        }else if(comparator.compare(list.get(iMid), Key) < 0){
            return search(list, Key, iMid+1, iMax, comparator);
        }else{
            return iMid;
        }
    }

    public static void main(String[] args) {
        GenericBinarySearch bs = new GenericBinarySearch();
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);

        int key = 2;
        int iMin = 0;
        int iMax = list.size()-1;

        //Java 8 - Lambda expressions 
        // new Comparator( public T int compare(T o1, T o2) {
        //      return o1.compareTo(o2);
        // }) ---> same expression is replaced by 
        // (T o1, T o2) -> o1.compareTo(o2) or (o1,o2) -> o1.compareTo(o2)   
        int index = bs.search(list, key, iMin, iMax, (o1,o2) -> o1.compareTo(o2));
        System.out.println(index);
    }


}