C++实现二分查找(递归方法和非递归方法)

来源:互联网 发布:vb断点调试 编辑:程序博客网 时间:2024/05/21 10:00

需要注意的一个地方:middle=start+(end-start)/2;//假如,left与right之和超过了所在类型的表示范围的话,那么middle就不会得到正确的值.所以写成这种形式稳妥

另外一个需要注意的地方就是,二分搜索只能够用于搜索排序了的数组,如果数组没有排序那么下面的方法就不起作用了。而且要是要用下面的两个程序,数组还需要默认的采用的是从小到大的排序方式。

#include<iostream>

using namespace std;
bool IsInvalidInput=false;
int BinarySearch(int *data,int length,int start,int end,int k)//二分查找,data必须是一个排序的数组。在这里默认data是按照升序排序的数组
{
if(data==NULL||length<0||start<0||end<0||start>end)
{
IsInvalidInput=true;
return -1;
}
while(start<=end)
{                   
int middle=start+(end-start)/2;//假如,left与right之和超过了所在类型的表示范围的话,那么middle就不会得到正确的值.所以写成这种形式稳妥
if(data[middle]<k)
start=middle+1; //一定注意start千万不能置为middle。如果这里把start,end设置middle很可能就会导致死循环
else if(data[middle]>k)
end=middle-1;//注意end千万不能置为middle
else
return middle;
}
return -1;
}
int BinarySearch_recurse(int *data,int length,int start,int end,int k) //递归实现二分查找(折半搜索)
{
if(data==NULL||length<0)
{
IsInvalidInput=true;
return -1;
}
if(start<=end)
{
int middle=start+(end-start)/2;
if(data[middle]<k)
BinarySearch_recurse(data,length,middle+1,end,k);
else if(data[middle]>k)
BinarySearch_recurse(data,length,start,middle-1,k);
else
return middle;
}
else
return -1;


}


int main()
{
int data[]={1,3,6,6,7,8,8,8,9};
int length=sizeof(data)/sizeof(int);
int k=6;
//int result=BinarySearch(data,length,0,length-1,k);
int result=BinarySearch_recurse(data,length,0,length-1,k);
if(!IsInvalidInput)
{
if(result==-1)
cout<<"Don't have"<<endl;
else
cout<<data[result]<<"位置: "<<result<<endl;
}
return 0;

}

二分查找时间复杂度的计算:

二分查找最好最好时间复杂度是O(1)不用说。
最差时间复杂度如下:


二分查找的平均时间复杂度:

第1次查找,能定位1个位置,恰好找到的概率是1/n
第2次查找,能定位2个位置,恰好找到的概率是2/n
第3次查找,能定位4个位置,恰好找到的概率是4/n
......
第m次查找,能定位2^m-1个位置,恰好找到的概率是(2^m-1)/n

由于只有n个位置,假设最多查找m次,m根据以下方法计算出来。

下面计算查找次数的期望。


上面的方法,查找某个数在数组中的位置,如果数组中存在多个要查找的某个数的时候,那么上面的方法就随机的返回其中的任意一个位置。如果要求我们返回要查找的某个数第一次出现的位置,那么需要修改上面的程序:

#include<iostream>
using namespace std;
bool IsInvalidInput=false;
int BinarySearch(int a[],int length,int start,int end,int k)
{
if(a==NULL||length<0||start>length-1||end>length-1||start<0||end<0||start>end)
{
IsInvalidInput=true;
return -1;
}
while(start+1<end)
{
int middle=start+(end-start)/2;
if(a[middle]<k)
start=middle;//注意这里不能够写为middle+1形式,这样写的话计算数字在数组中第一次出现的位置的话会出现错误
else
end=middle;
}
if(a[end]!=k)
return -1;
else
return end;
}
int main ()
{
int a[]={1,2,3,4,5,6,6,6,8,9};
int length=sizeof(a)/sizeof(int);
int k=6;
int result=BinarySearch(a,length,0,length-1,k);
if(IsInvalidInput)
cout<<"Input is Invalid"<<endl;
else
{
if(result==-1)
cout<<"can't find"<<endl;
else
cout<<result<<endl;
}
return 0;
}

上面的改进的二分搜索程序比之前的更高效。在每次循环迭代中,它只对要查找的某数和数组中的元素做一次比较,而之前的程序有可能需要比较两次

0 0
原创粉丝点击