前言
二分查找是一种比较高效的查找方式,使用此查找方式需要先将数组进行排序,如果数组未经排序效率就会很低,所以数组是必须要经过排序的。
查找原理
代码实现
@Test
public void test1() {
Integer[] arr = new Integer[]{4, 3, 2, 1, 5, 10, 1, 11, 1, 1, 2, 123, 42142, 1};
arr = mergeSort(arr, Comparator.naturalOrder()); //使用二分法需要先将数组排序 (归并排序)
for (Integer integer : arr) {
System.out.println(integer);
}
System.out.println(binarySearch(arr, 42142, 0, arr.length, Comparator.naturalOrder()));
}
/**
* 使用二分法查找元素,如果有多个仅仅只返回其中一个数组下标(乱序)。
*
* @param arr 目标数组
* @param find 查找元素
* @param start 数组开始下标
* @param end 数组结束下标
* @param comparator 元素比较规则
* @return 查找的元素在目标数组的下标
*/
private int binarySearch(Object[] arr, Object find, int start, int end, Comparator comparator) {
if (arr == null) throw new NullPointerException("arr can not be empty!");
int middle = (end - start) / 2 + start;
int result = comparator.compare(arr[middle],find);
if(middle == 0 && result != 0) return -1;
if(result > 0) {
return binarySearch(arr, find, start, middle, comparator);
} else if(result < 0) {
return binarySearch(arr, find, middle, end, comparator);
} else {
return middle;
}
}
/**
* 归并排序
*
* @param arr 排序数组
* @param comparator 比较规则
* @return 排序后的数组
*/
private <T> T[] mergeSort(T[] arr, Comparator<T> comparator) {
T[] cache = arr.clone();
int step = 2;
while (step <= arr.length * 2) {
int c = 0;
for (int i = 0; i < arr.length; i += step) {
int l = i, r = l + (step >> 1) > arr.length ? arr.length : i + (step >> 1);
int lm = r;
int rm = i + step > arr.length ? arr.length : i + step;
while (l < lm && r < rm) {
if (comparator.compare(arr[l],arr[r]) > 0) {
cache[c] = arr[r];
r++;
c++;
} else {
cache[c] = arr[l];
l++;
c++;
}
}
while (l < lm) {
cache[c] = arr[l];
l++;
c++;
}
while (r < rm) {
cache[c] = arr[r];
r++;
c++;
}
System.arraycopy(cache, 0, arr, 0, cache.length);
}
step = step << 1;
}
return (T[]) cache;
}
归并排序可以参考 > 归并排序