必要条件:给定的数组必须有序,否则不适用二分查找。如果传入的数组无序,则要先对其排序,再进行二分,查找。那排序问题可参考其它排序算法。这篇博文的重点是讲二分。
核心思路:二分区间,找到划分的区间中点位置的元素,与输入比较
具体实现步骤:
1)设置查找区间的左端点 l,初始化为原数组的最小的索引。
2)设置查找区间的右端点 r,初始化为原数组的最大索引。
3)只要左端点值小于等于右端点值,从第4步开始进行操作;否则结束循环,查找完毕,返回一个标志如-1,表示在数组中都没找到与value相等的值,不再进行下面的操作。
4)对给定的区间开始二分,得到数组的中点位置元素的索引mid=l+(r-l)/2
5) 将区间中点的元素与查找目标比较。
6)若目标元素与区间中间位置的元素相等,则返回目标元素在原数组中索引,并结束查找,不再进行下面的操作;否则进行下面的步骤。
7)若目标元素小于区间中间位置的元素,说明查找目标可能存在于较小的区间内,所以调整右端点的索引,r=mid-1,使查找范围变为两个查找区间中较小的一个,跳转到第4步执行。
8)若目标元素大于区间中间位置的元素,说明查找目标可能存在于较大的区间内,所以调整左端点的索引l=mid+1,使查找范围变为两个查找区间中较大的一个,跳转到第4步执行。
温馨提示:计算中点mid=l+(r-l)/2与mid=(l+r)/2,人算的话都可以,因为人的大脑存储信息不像电脑那般固定大小,对于固定数据类型存储空间的机器来说,计算l+r是存在bug的。
我们知道,数据类型在计算机里存储都是有长度限定的。
如果l和r都很大,快接近某种类型的最大值了。
那计算机计算l+r,就会得到错误结果,因为计算结果很容易就超过这种类型所能存储的最大容量,因而会把计算结果高位溢出,这样显然的不到正确结果。
而l+(r-l)/2这种方式就不会存在上述问题,因为r和l如果在编译时都不报错,那r-l显然也不会存在问题,把r-l的结果除以2再与l相加,也不会存在问题,所以整个计算过程都不会有问题,这也是二分查找中很关键的一步。
代码实现与详细解读:
package compute;
/**
* 二分查找
*@create by gzx on 2022-2-11
*/
public class BinarySearch {
public static void main(String[] args) {
int[] src= {1,2,3,5,6,7,7,8,9};
int i = search(src, 10);
System.out.println(i);
int j = search(src, 0);
System.out.println(j);
int k = search(src, 7);
System.out.println(k);
int m = search(src, 4);
System.out.println(m);
int n = search(src, 6);
System.out.println(n);
}
/**
* @param src 原数组,必须为有序数组
* @param target 要在数组src中查找的目标值
* @return 首次在src中找到的、与target相等的元素的下标
*/
public static int search(int[] src,int taget) {
int l=0;//左端点,初始化为原数组的最小的索引
int r=src.length-1;//右端点,初始化为原数组的最大索引
while(l<=r) {//说明还没有二分完毕
int mid=l+(r-l)/2;//对给定的区间开始二分,得到数组的中点位置元素的索引
if (taget==src[mid]) {//表示查找到目标
return mid;//返回目标元素在原数组中索引,并结束查找,不再进行下面的操作
}
if (taget<src[mid]) {//说明查找目标可能在较小的区间内
r=mid-1;//所以调整右端点的索引,使查找范围变为两个查找区间中较小的一个
}else{//说明查找的目标可能在较大的区间内
l=mid+1;//所以调整左端点的索引,使查找范围变为两个区间较大的一个
}
}
return -1;//二分遍历完毕,在数组中都没找到与value相等的值,则返回下标-1表示未找到
}
}
对数组{1,2,3,5,6,7,7,8,9}进行五次查找操作
int i = search(src, 10);
System.out.println(i);
int j = search(src, 0);
System.out.println(j);
int k = search(src, 7);
System.out.println(k);
int m = search(src, 4);
System.out.println(m);
int n = search(src, 6);
System.out.println(n);
查找结果
-1
-1
6
-1
4