1,先给出一个经常用到的代码:
#include<iostream>
using namespace std;
int binarySearch1(int t, int data[], int n)
{
int l = 0;
int u = n - 1;
int p, m;
while (true)
{
if (l > u)
{
p = -1;
break;
}
m = (l + u) / 2;
if (data[m] < t)
l = m + 1;
else if (data[m] == t)
{
p = m;
break;
}
else
u = m -1;
}
return p;
}
int main()
{
int data[]={1,4,4,5,6,8,9,9,9,9,9,10};
int n=sizeof(data)/sizeof(data[0]);
cout<<binarySearch1(9,data,n)<<endl;
return 0;
}
缺点:
(1)每次循环至少需要比较两次;
(2)如果t多次出现,那么上述代码可能返回t的任意一个位置.
2,下面改进的代码,可以保证返回t第一次出现的位置.
#include<iostream>
using namespace std;
int binarySearch2(int t, int data[], int n)
{
int l = -1;
int u = n;
int m;
while ( (l + 1) != u)
{
m = (l + u) / 2;
if (data[m] < t)
l = m;
else
u = m;
}
int p = u;
if ((u >= n) || (data[u] != t))
p = -1;
return p;
}
int main()
{
int data[]={1,4,4,5,6,8,9,9,9,9,9,10};
int n=sizeof(data)/sizeof(data[0]);
cout<<binarySearch2(9,data,n)<<endl;
return 0;
}
3,继续改进,循环展开将会有很大的提高.
#include<iostream>
#include<algorithm>
#include<iterator>
using namespace std;
const int N=1000;
int data[N];
int randInt()
{
return rand()%(5000);
}
//这里设定数组的大小为1000
int binarySearch3(int t,int data[],int n)
{
//第一步先保证搜索的范围为2的指数次.
int i=512;
int l=-1;
if(data[511]<t)
l=1000-512;
while(i!=1)
{
if(data[l+i/2]<t)
l=l+i/2;
i=i/2;
}
//assert:i==1;data[l]<t;data[l+i]>=t
int p=l+1;
if(p>=n||data[p]!=t)
p=-1;
return p;
}
int binarySearch4(int t,int data[],int n)
{
//第一步先保证搜索的范围为2的指数次.
int l=-1;
if(data[511]<t)
l=1000-512;
if(data[l+256]<t) l+=256;
if(data[l+128]<t) l+=128;
if(data[l+64]<t) l+=64;
if(data[l+32]<t) l+=32;
if(data[l+16]<t) l+=16;
if(data[l+8]<t) l+=8;
if(data[l+4]<t) l+=4;
if(data[l+2]<t) l+=2;
if(data[l+1]<t) l+=1;
//assert:i==1;data[l]<t;data[l+i]>=t
int p=l+1;
if(p>=n||data[p]!=t)
p=-1;
return p;
}
int main()
{
generate(data,data+N,randInt);
sort(data,data+N);
copy(data,data+N,ostream_iterator<int>(cout," "));
cout<<endl;
cout<<binarySearch3(447,data,N)<<endl;
cout<<binarySearch4(447,data,N)<<endl;
return 0;
}