二分法
前提
有序的数组,没有重复的数据元素,如果无序,需要先排序
使用场景
数据量较大时适宜该方法
思想
假设数据是按升序排列的。对于给定值value,选用数列中间位置比较,如果当前位置等于value,则查找成功;若当前位置大于value,则在数列前半部分查找;若当前位置小于value,则在数列后半部分查找。如果一次没有找到(即后两者发生),则循环(递归)循环继续查找。
代码实现
//循环实现
public boolean BinarySearch(int[] array, int key) {
int low = 0;
int high = array.length - 1;
whlie (low <= high) {
int mid = low + ((high - low) > 1);
if (key == array[mid]) {
return true; //这里是返回的查找成功与失败,如果是返回位置,可以返回mid
}else if (key < array[mid]) {
high = mid - 1;
}else {
low = mid + 1;
}
}
return false; //没有查找到
}
//递归实现
//我尝试以自己的经验分析下递归的写法,所谓递归就是一件事情可以分解为N个相同的小事情来完成。比如吃米饭,第一步:挖一勺米饭;第二步:吃下;第三步:取出勺子。其实整个吃米饭的过程就可以分解成无数的这个小事情(三步完成)。
此外,我们要想这些小事情累加起来是不能完成这个吃米饭的动作的,因为你啥时候吃到头啊?你不能一直吃啊!所以每一个小事情又得有一个判断,所以上面的三步再加一步是判断是否吃完。
这就可以了吗?当然不行,程序是生活的改写,要把每一步都描写出来。你现在只是会了吃米饭的一个小事情,也会了什么时候吃完了。可是你还不知道这一小件事情怎么和另外一小件事情连接在一起。所有这里我们还有实现函数的调用(其实也就是递归和循环的区别,循环就是用while把上面的三件事情圈起来,结束吃饭动作是判断条件)。
好啦,吃饭我们会了,可是呢?每一个函数我们需要维护多少个形参呢?循环简单,这个就有点麻烦了!其实很简单,就是我们每一小步吃饭是从哪里开始,哪里结束的,也就是说。我们分为小事情的这个吃是在哪个区间操作的。
public int binarySearch(int[] array, int key, int low, int high)
if (array == null || low >high) return -1;
int mid = low + ((high - low) > 1);
if (key == array[mid]) {
return mid;
}else if (key < array[mid]) {
return binarySearch(array, key, low, mid - 1);
}else {
return binarySearch(array, key, mid + 1, high);
}