首先说明一点,某些代码在边界判断存在细微差别,至于原理很多时候需要查找原始文献,有时候查了也不懂,可能这就是精髓,只可意会,不可言传。所以,我只是列出区别,比较记忆,原理在学会使用以后慢慢品味理解。或许某时刻就会茅塞顿开。
二分查找的最简单代码:
输入:A[start,start+1,......,end-1,end]//按照由小到大的顺序排列
输出:和val相等的元素的下标;假如不存在则输出-1;
循环不变式:貌似是A[start]<=val&A[end]>=val。
int BIN_FIND_ORI(int A[],int start,int end,int val)
{
int temp;
if(A[start]>val||A[end]<val)
return -1;//首先判断在此范围内是否可能存在
while(start<=end)
{
temp=(start+end)/2;//常见的另外一种写法start+(end-start)/2;
if(A[temp]==val)
return temp;
else if(A[temp]<val)
start=temp+1;
else
end=temp-1;
}
return -1;
}
输入:A[start,start+1,......,end-1]
输出:同上
循环不变式:A[start]<=val&A[end]>val
int BIN_FIND_Better(int A[],int start,int end,int val)
{
int temp;
if(A[start]>val||A[end]<val)
return -1;
while(end-start>1)
{
temp=start+(end-start)/2;
if(A[temp]<=val)
start=temp;
else
end=temp;
}
if(A[start]==val)
return start;
return -1;
}
在上述两种方法的基础上做一下扩展:
扩展一:利用迭代器实现
利用上边的方法二进行扩展,所以end位置上是没有元素的
int BIN_FIND_IT(vector<int> A,int start1,int end1,int val)
{
if(A.begin()==A.end())//数组为空的情况
return -1;
if(A[start1]>val||A[end1-1]<val)
return -1;
auto beg=A.begin();
auto end=A.end()+end1;//指到最后一个元素的下一个位置
while(end-beg>1)
{
auto temp=beg+(end-beg)/2;
//此处一定需要注意,是不能用(beg+end)/2这种形式的,会发生越界错误。
//所以大家记住以后就用上述形式就行了。越界理由参考C++第五版,练习3.26
if(*temp<=val)
beg=temp;
else
end=temp;
}
if(*start==val)
return beg-A.begin();
return -1;
}
扩展二:这个方法是一种全新的思路,变动的是数组的首位置;
int BIN_FIND_Point(int A[],int start,int end,int val)
{
if(A[start]>val||A[end-1]<val)
return -1;
int num=end-start;//最后一个位置仍旧没有元素
int *p=&A[start];
int temp=0;
while(num>1)
{
temp=num>>1;//元素个数减半
if(p[temp]<val)
{
p+=temp+1;
num-=temp+1;
}
else if(p[temp]>val)
num=temp;
else
return p+temp-&A[start];
}
if(p[0]==val) return p-&A[start];
return -1;
}