Java中的二分查找
在Java.util中有两个类,Arrays和Collectons,可以方便快捷的帮我们处理一些数组和集合的问题。
它们里边都一个一个二分法查找的方法:
Arrays.binarySearch
public static int binarySearch(long[] a, long key) { return binarySearch0(a, 0, a.length, key); }
private static int binarySearch0(long[] a, int fromIndex, int toIndex, long key) { int low = fromIndex; int high = toIndex - 1; while (low <= high) { int mid = (low + high) >>> 1; long midVal = a[mid]; if (midVal < key) low = mid + 1; else if (midVal > key) high = mid - 1; else return mid; // key found } return -(low + 1); // key not found. }
Collections.binarySearch:
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) { if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD) return Collections.indexedBinarySearch(list, key); else return Collections.iteratorBinarySearch(list, key); }
private static <T> int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) { int low = 0; int high = list.size()-1; while (low <= high) { int mid = (low + high) >>> 1; Comparable<? super T> midVal = list.get(mid); int cmp = midVal.compareTo(key); if (cmp < 0) low = mid + 1; else if (cmp > 0) high = mid - 1; else return mid; // key found } return -(low + 1); // key not found }
其核心算法是一致的,区别就在于Arrays支持数组,Collectons针对的是实现List接口的集合。
public class BinarySearch { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); int i = 1; while(i<10) { list.add(i); i++; } Integer key=11; Integer result = binarySearch(list, key); System.out.println(result); } private static Integer binarySearch(List<Integer> list, Integer key) { int min = 0; int max = list.size()-1; while(min<max) { int mid = (max+min)>>>1; Integer integer = list.get(mid); int compareTo = integer.compareTo(key); if(compareTo<0) { //代表我们查询的这一半中的最大值都小于我们要找的元素 min=mid+1; }else if(compareTo>0) { //代表我们要查询的这一半中可能由我们要找的元素 max=mid-1; }else { return mid;//直到找到中间的那一个 } } return -(min+1); } }
1.首先确定最大索引和最小索引
2.以min<max为条件做循环判断,每次都获取一个中间索引。然后获取这个索引所对应的元素和我们要查找的数值进行判断。
在判断时调用的时Integer这个类的compareTo方法进行比较。所有想要调用这个方法的类只需要实现Comparable这个接口
![]()
然后就可以自定义自己的compareTo方法。(这个接口是一个进行比较的规则,里边也就只有compareTo这一个方法)。
在Integer中这个方法是这样实现的:
public int compareTo(Integer anotherInteger) { return compare(this.value, anotherInteger.value); } public static int compare(int x, int y) { return (x < y) ? -1 : ((x == y) ? 0 : 1); }
也就是使用三元运算法则对两个值进行比较,如果元素小于我们要找的值,返回-1,如果元素大于我们要找的值返回1,如果找到了,就返回0.
3.如果我们mid对应的元素小于我们要找的元素,那么就去另一半寻找,最小索引变为mid+1;
如果我们mid对用的元素大于我们要找到元素,那么说明元素可能在这半个区间中,缩小范围继续寻找,将max变为mid-1;
如果我们要找的值在集合和数组中不存在,就返回一个负值。值的大小为-(中间索引数+1);
需要注意的是,因为二分法查找是元素大小进行判断的,所以要想是结果正确,首先要对集合进行一次排序。

浙公网安备 33010602011771号