当一个数组需要用到查找方法时,可以遍历整个数组,找到相等的值返回下标,这种方法效率比较低。如果这个数组是有序的,我们可以使用二分查找(折半查找)。二分查找是将数组不断的分成两段,判断我们要找的数据与中值是否相等。
如果我们有这样一个数组 int [] arr={0,10,20,30,40,50,60,70},使用二分查找找到60;
我们首先要找到中值30与60对比,30与60 是不等的,并且60比30 大,所以我们在40与70之间的中值50 与60相比,50与60也是不等的,并且60比50大,所以,让60与70之间的中值60 与60是相等的,所以返回中值60的下标,代码如下:
public static int binarySearch(int[] arr,int key){
int max,min,mid;
min=0;
max=arr.length-1;
mid=(max+min)>>1; //右移一位相当于除2运算。
while(arr[mid]!=key){ //当中值与要找的数据不相等,进入循环
if (key>arr[mid]) { //如果数据比中值大
min=mid+1; //让最小下标放在中值后面,找较大的另一半数据
}
else if(key<arr[mid]){ //如果数据比中值小
max=mid-1; //让最大下标放在中值前面,找较小的另一半数据
}
if (max<min) { //当最大下标比最小下标小时,说明数据不存在
return -1;
}
mid=(max+min)>>1;
}
return mid; //当中值与要找的数据相等,说明数据找到,返回中值的下标。
}
所以我们也可以换一种方式写这段代码,当最小小标小于等于最大下标,说明数据存在,进入循环折半查找,反之,说明数据不存在,循环结束返回-1.
public static int binarySearch(int[] arr,int key){
int max,min,mid;
min=0;
max=arr.length-1;
mid=(max+min)>>1;
while(min<=max){
mid=(max+min)>>1;
if (key>arr[mid]) {
min=mid+1;
}
else if(key<arr[mid]){
max=mid-1;
}
else
return mid;
}
return -1;
}
那么,如果给定一个有序的数组,如果往数组中插入一个元素还保证数组有序,那么元素的脚标位改如何获取?
当一个数组初始化完毕,数组的个数是固定的,没有办法在数组里面增加元素,但是我们是可以获取它的脚标位的。如果我们要插入的这个元素数组里面没有,我们要找到这个元素的插入点我们知道,当max<min 的时候确定了元素其实是不存在的,因为max移到了min 的前面还是没找到,此时min所指的位置其实就是插入点,因为min刚好大一位。所以我们让没找到元素时的返回值为min即可。所以上述代码,把return -1改成return min就可以解决这个问题了。
Java也是有二分查找方法的,Array.binarySearch();是Java自带的二分查找方法,如果我们调用这个方法:
能够找到数据的下标为6,如果数据不存在呢?
我们看到,当数据不存在时,它的返回值成了负数,这个负数其实是这个数据的插入点减一。55在数组之中的插入点应该是6,但这个数据其实是不存在的,所以用负数表示不存在的含义,也就是-6,但是我们为了解决和0冲突的问题,所以就让插入点减一。(试想如果我们要查找-1,插入点应该是0,但是如果我们不减去一,那就和零冲突了)。总而言之,Java真是一个贴心的存在啊,,虽然Java给我们提供了方法,但是必要的知识我们还是应该知道的。