代码需求如下:
/*
* 二分法查找操作:使用二分法查找有序数组中元素。找到返回索引,不存在 输出-1。
* 分析:二分法查找的前提是数组有序。
* 假如有一组数为3,12,24,36,55,68,75,88要查给定的值24.可设三个变量front
* ,mid,end分别指向数据的上界,中间和下界,mid=(front+end)/2.
*/
原始代码如下:
public class Test29{
public static void main(String[] args){
int[] arr = {3,12,24,36,55,68,75,88};
Arrays.sort(arr);
//数组上界、下界、中间值
int front = 0;
int end = arr.length-1;
int mid = 0;
Scanner sc = new Scanner(System.in);
System.out.println("请输入要查找的整数:");//输入5出现Bug,why? front=0,end=1 进入死循环
int num = sc.nextInt();
//记录查询次数
int count = 0;
//输入数据是否存在于数组中,true表示存在,false表示不存在
boolean flag = false;
while(front <= end){
count++;
/* if(front > end){//front不可能大于end
break;
} */
mid = (front + end) / 2;
if(num > arr[mid]){
front = mid;
}else if(num == arr[mid]){
flag = true;
break;
}else{
end = mid;
}
}
if(flag){
System.out.println("该数据位于数组索引" + mid + "处," + "查找次数:" + count);
}else{
System.out.println("-1," + "查找次数:" + count);
}
}
}
这段代码写完之后,粗看没发现什么bug,但是测试的时候出现了问题,输入数字5之后进入了死循环。此时front=0,end=1。此时开始反推逻辑,其实在if的第二个分支,已经将输入的数值与中间值进行了比较,所以需要将插入的索引位置前移或后移。如果不进行这种操作,那么就很可能进入一直与中间值比较的情况,从而进入死循环。
于是翻看了Arrays类下面的二分法查找源码:
private static int binarySearch0(int[] a, int fromIndex, int toIndex,
int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int 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.
}
很明显,源码在进行中值操作的时候,进行了前移(
high = mid - 1)或后移(
low = mid + 1),这样就避免了进入无限与中值比较的情况。
修改代码如下,问题解决:
import java.util.Arrays;
import java.util.Scanner;
public class Test29{
public static void main(String[] args){
int[] arr = {3,12,24,36,55,68,75,88};
Arrays.sort(arr);
//数组上界、下界、中间值
int front = 0;
int end = arr.length-1;
int mid = 0;
Scanner sc = new Scanner(System.in);
System.out.println("请输入要查找的整数:");//输入5出现Bug,why? front=0,end=1 进入死循环
int num = sc.nextInt();
//记录查询次数
int count = 0;
//输入数据是否存在于数组中,true表示存在,false表示不存在
boolean flag = false;
while(front <= end){
count++;
/* if(front > end){//front不可能大于end
break;
} */
mid = (front + end) / 2;
if(num > arr[mid]){
front = mid + 1;
}else if(num == arr[mid]){
flag = true;
break;
}else{
end = mid - 1;
}
}
if(flag){
System.out.println("该数据位于数组索引" + mid + "处," + "查找次数:" + count);
}else{
System.out.println("-1," + "查找次数:" + count);
}
}
}