二分查找是一种查询效率非常高的查找算法。又称折半查找。
起初在数据结构中学习递归时实现二分查找,实际上不用递归也可以实现,毕竟递归是需要开辟额外的空间的来辅助查询。本文就介绍两种方法
其缺点是要求待查表为有序表,且插入删除困难。
因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
使用条件:查找序列是顺序结构,有序。
//二分查找递归实现
public static int binaryserach_recursion(int arr[],int aimnum,int low,int high){
if (aimnum<arr[low] || aimnum > arr[high] || low > high){
return -1;
}
int middle=(high+low)/2;
if (aimnum > arr[middle]){
return binaryserach_recursion(arr,aimnum,middle+1,high);
}else if (aimnum < arr[middle]){
return binaryserach_recursion(arr,aimnum,low,middle-1);
}else {
return middle;
}
}
为何有了递归我们还要去看非递归呢?因为我们知道每当我们调用一个函数JVM会在会在虚拟机栈中创建一个栈帧,那么当我们递归次数不多当然看不出来,当递归的次数过多,那么我们就会撑爆虚拟机栈导致栈溢出。
//二分查找非递归实现
public static int binarySearch_loop(int arr[],int aimnum,int low,int high){
if (aimnum<arr[low] || aimnum > arr[high] || low > high){
return -1;
}
int middle=0;
while (low <= high){
middle=(low+high)/2;
if (arr[middle] < aimnum){
low = middle+1;
}else if (arr[middle] > aimnum){
high=middle-1;
}
else return middle;
}
return -1;
}
我们在前面看到我们每次算两个数的平均数数时使用的是int middle=(low+high)/2; 这个在我们int范围内当然没事,但是当我们数据过大会导致溢出问题!
int right=(high-low+1)/2+low
public static int mean(int a, int b){
return (x & y) + ((x ^ y) >> 1);
}
class IndexNode{
int index;
Boolean flag;
public IndexNode(int index, Boolean flag) {
this.index = index;
this.flag = flag;
}
}
public class BinarySerach_withNode {
public static IndexNode binarySerach(int arr[],int aimnum){
IndexNode pos=new IndexNode(-1,false);
int low=0;
int high=arr.length-1;
int middle=0;
while (low <= high){
middle=(high-low+1)/2+low;
if (aimnum > arr[middle]){
low=middle+1;
}else if (aimnum < arr[middle]){
high=middle-1;
}else {
pos.index=middle;
if (arr[middle]==aimnum){
pos.flag=true;
}else {
pos.flag=false;
}
break;
}
}
return pos;
}
public static void main(String[] args) {
int arr[]={
1,2,3,4,5,67,75,88,99};
IndexNode pos=binarySerach(arr,0);
System.out.println(pos.index );
System.out.println(pos.flag);
}
}