1、二分查找法是我们常用的查找法,要使用它有一个前提条件:数组必须有序,递增或者递减;
2、二分查找的优点:比较次数较少、查找速度快、平均性能好;
3、二分查找的缺点:待查表为有序表,插入困难;由此延伸为顺序结构中,插入与删除比较困难;
4、二分查找的思想:
步骤一:首先确定整个查找区间的中间位置mid = (end - start)/2;
步骤二:用待查关键字值与中间位置的关键字值进行比较,若相等,则返回中间下标;
若不相等,有两种情况:
若array[mid] > key:查找范围缩小为左半区域,具体表现为:statrt不变,end = mid - 1;
若array[mid] < key:查找范围缩小为右半区域,具体表现为:end不变,start = mid + 1;
步骤三:对确定的缩小区域再进行折半公式,重复以上步骤!
注意的点:在使用if时一定要确定好是否还可以继续if的条件,那就是:start <= end,只有在这个条件底下,才可以查询!!!
5、来看非递归代码的实现:
public class BinSreach {
public static void main(String[] args) {
int arr[] = {2,4,6,7,8,9,10,17,19,20,34,78,89};
int aimIndex = BinarySreach(arr, 19);
System.out.println(aimIndex);
}
//一般方法
public static int BinarySreach(int[] arr, int key) {
//在这里提前判断一下数组是否为空,如果为空,那就没必要在查找了
if(arr == null) {
return -1;
}
//若不为空,则进行如下操作
int start = 0; //定义开始下标
int end = arr.length - 1; //定义末尾下标
int mid = 0; //定义中间下标
//先使用中间值与关键字值进行比较
if(arr[arr.length/2] == key) {
return arr.length/2;
}
//如果中间值与关键字值不相等,进行一下查找。start <= end是一个非常重要的条件,只有在符合这个条件的前提下,才可以进行查找
while(start <= end) {
//这也是一个相当重要的公式,用于在小范围内查找中见下标,所有的中间下标都是基于这个小范围来说的
//它具体的值都是基于整个数组的顺序来说的,所以要在末尾加上start
mid = (end - start)/2 + start;
if(arr[mid] > key) { //当中间值大于关键字的情况
end = mid - 1; //缩小为作左边范围
} else if(arr[mid] < key) { //当中间值小于关键字的情况
start = mid + 1; //缩小为右边范围
} else{ //若是两个小范围都不符合以上两种情况,那就是在小范围内相等的情况了
return mid;
}
}
return -1;
}
}
代码的每一行几乎都有注释,写的挺清楚的,哪里有漏洞,请大家多多指教呀~
结果如下:
6、使用递归方法实现:
在看代码之前,我想给大家说一个很重要的事情:在写递归的时候一定要考虑到这个递归结束的条件!!!
在看代码之前,我想给大家说一个很重要的事情:在写递归的时候一定要考虑到这个递归结束的条件!!!
在看代码之前,我想给大家说一个很重要的事情:在写递归的时候一定要考虑到这个递归结束的条件!!!
可能是自己的代码量太少了,所以在昨天尝试使用递归时,写完程序发现运行结果不对,首先是自己忘了将结果return一下。后来将关键字换为一个不在数组中的数字,发现下标标越界错误,原来是没有写结束的条件:start > end,希望大家引以为戒!
/**
* @author 橙橙橙。
* Date:2019.03.15
* 题目:使用递归方式实现二分查找
* 步骤:不断地使用中间查找法
* 写完之后的问题:没有加return,导致结果输出错误
*/
public class BinSreach2 {
public static void main(String[] args) {
int arr[] = {2,4,6,7,8,9,10,17,19,20,34,78,89};
int aimIndex = BinSreachOfRecursion(arr,0,arr.length-1,89);
System.out.println(aimIndex);
}
public static int BinSreachOfRecursion(int[] arr, int start, int end,int key) {
if(arr == null) {
return -1;
}
//这个判断,必不可少,因为它就是递归种植的条件呀~
if(start > end) {
return -1;
}
int mid = (end - start)/2 + start;
if(arr[mid] > key) {
//在这个,一定要有return
return BinSreachOfRecursion(arr, start, mid-1, key);
} else if(arr[mid] < key) {
//在这个,一定要有return
return BinSreachOfRecursion(arr, mid+1, end, key);
} else {
return mid;
}
}
}
由于在非递归查找时,已经写过详细过程,此处代码不再赘述;
结果:
二分查找告一段落,下回分解:老掉牙的快速排序~
生活就像一汪海洋,只有意志坚定的人,才可以走到彼岸!相信你也是个意志坚定的人~