二分作为一种方法,或者说是一种思想,是很常用的,也是很好用的,所以介于我的二分能里比较弱,今天我就来总结整理一些知识,供大家分享。
说明:本文章参考于——http://blog.youkuaiyun.com/sunmenggmail/article/details/7540970
一.可能出现的一些问题
1.边界错误造成的问题
二分查找算法的边界,一般来说分两种情况,一种是左闭右开区间,类似于[left, right),一种是左闭右闭区间,类似于[left, right].需要注意的是, 循环体外的初始化条件,与循环体内的迭代步骤, 都必须遵守一致的区间规则,也就是说,如果循环体初始化时,是以左闭右开区间为边界的,那么循环体内部的迭代也应该如此.如果两者不一致,会造成程序的错误。如果两者同时都写错的话,可能会造成死循环。
2.溢出
假如,left与right之和超过了所在类型的表示范围的话,那么middle就不会得到正确的值.
二.代码实现
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[10];
int lowserach(int b[],int x,int y,int v)//注意求比其小的一项应减 1
{
int m;
while(x<y)
{
m=x+(y-x)/2;
if(b[m]>=v)y=m;
else x=m+1;
}
return x;
}
int upserach(int b[],int x,int y,int v)
{
int m;
while(x<y)
{
m=x+(y-x)/2;
if(b[m]<=v)x=m+1;
else y=m;
}
return x;
}
int findserach(int b[],int x,int y,int v)
{
int m;
while(x<=y)
{
m=x+(y-x)/2;
if(b[m]==v)return m;
else if(b[m]>v)y=m-1;
else x=m+1;
}
}
int Bi_Search(int a[],int n,int b)//返回等于b的第一个
{
if(n==0)
return -1;
int low = 0;
int high = n-1;
int last = -1;//用last记录上一次满足条件的下标
while (low<=high)
{
int mid = low +(high-low)/2;
if (a[mid]==b)
{
last = mid;
high = mid -1;
}
else if(a[mid]>b)
high = mid -1;
else
low = mid +1;
}
return last;
}
int Bi_Search1(int a[],int n,int b)//大于b的第一个数
{
if(n<=0)
return -1;
int last = -1;
int low = 0;
int high = n-1;
while (low<=high)
{
int mid = low +(high - low)/2;
if(a[mid]>b)
{
last = mid;
high = mid -1;
}
else if (a[mid]<=b)
{
low =mid +1;
}
}
return last;
}
int Bi_Search2(int a[],int n,int b)//小于b的第一个数
{
if(n<=0)
return -1;
int last = -1;
int low = 0;
int high = n-1;
while (low<=high)
{
int mid = low +(high - low)/2;
if(a[mid]<b)
{
low =mid +1;
last = mid;
}
else if (a[mid]>=b)
{
high = mid -1;
}
}
return last;
}
int main()
{
freopen("1.txt","r",stdin);//1 3 5 5 5 8 8 9
for(int i=1;i<=8;i++)
cin>>a[i];
int pos1,pos2;
pos1=upper_bound(a+1,a+9,7)-a;
pos2=lower_bound(a+1,a+9,7)-a;//注意求比其小的一项应减 1
cout<<pos1<<" "<<a[pos2]<<endl;
cout<<upserach(a,1,8,7)<<" "<<a[lowserach(a,1,8,7)]<<" "<<endl;//<<
cout<<Bi_Search1(a,8,7)<<" "<<a[Bi_Search2(a,8,7)]<<endl;
cout<<Bi_Search(a,8,7)<<" "<<findserach(a,1,8,7);
while(1);
return 0;
}
当然我们也可以用algorithm库中的二分函数:
pos=upper_bound(a,a+n,pos)-a;
pos=lower_bound(a,a+n,pos)-a;//注意求比其小的一项应减 1