通用二进制搜索Java

时间:2011-03-24 22:26:22

标签: java

我一直在努力使这段代码有效。我必须创建二进制搜索的通用二进制版本。我不确定如何在没有类似接口的情况下比较两种泛型类型

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.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");
    }
}

8 个答案:

答案 0 :(得分:10)

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

这将允许您的BinarySearcher为可以与compareTo进行比较的所有内容工作,这应该是通用的。

答案 1 :(得分:7)

您的通用方法无法比较某些任意类型T的两个实例,而不会对T有任何限制,或者有其他方式提供有关如何比较两个T的信息第

您有几个选择:

T添加约束:

public class BinarySearcher<T extends Comparable<T>>

或者将Comparator<T>传递给您可以调用的search方法进行比较:

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

旁注:我会避免在compareTo方法中拨打search两次;你不知道比较这两个对象是否昂贵。而不是:

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

做这样的事情:

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

答案 2 :(得分:1)

即使执行了上面建议的所有更改,您使用的条件也不正确(更改低指针和高指针),如果要返回索引,则需要在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;
    }
}

答案 3 :(得分:0)

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

答案 4 :(得分:0)

试试这个:

class BinarySearcher<T extends Comparable<T>>

答案 5 :(得分:0)

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

另一种选择是使用Comparator<T>; e.g。

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;
    }
}

可以通过修改原始构造函数来结合这两种方法,以使用比较器来转换它想要与Comparable实例进行比较的第一个值。这可能会进行不安全的转换,如果与T对应的实际类型实际上不是ClassCastException,则会导致Comparable


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

答案 6 :(得分:0)

正如其他人已经提到的那样,提升T扩展Comparable将解决您的问题。 Buuuut为什么要重新发明轮子?您可以轻松使用现有的通用Java二进制搜索:

System.out.println(Arrays.binarySearch(words, "November", null));

请注意,如果将null作为可比较参数传递,则采用自然元素顺序!

享受!

答案 7 :(得分:0)

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

Try
  con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Pradnya_DataB.mdb"
  con.Open()

  ds1 = New DataSet
  ss = "Select c1.cust_name,c1.cust_bottle_type,c2.B_Pending From Customer c1"
  ss = ss + " INNER JOIN Bottel_Collect c2 ON c2.Cust_ID=c1.Cust_ID WHERE c1.Cust_ID=" & CInt(lblText.Text)
  'ss = "Select * from Customer"

  da = New OleDbDataAdapter(ss, con)
  da.Fill(ds1)
  If ds1.Tables.Count > 0 Then
    TextBox2.Text = ds1.Tables("Custmor").Rows(0).Item(0).ToString()
    TextBox5.Text = ds1.Tables("Customer").Rows(0).Item(1).ToString()
    TextBox6.Text = ds1.Tables("Bottel_Collect").Rows(0).Item(5).ToString()
  End If
  con.Close()
  rd.Close()
Catch ex As Exception
  MsgBox(ex.Message)
End Try