今天看分治法那块,里面提到了二分搜索,想想好多年没写这个简单的程序了,话说当年第一个真正意义上理解的是三分查找,即二分搜索的拓展,所以根据分治法的思想,重新写了二分搜索,三分搜索这两个程序,突然回忆起来,当初对m=(l+r)/2,竟一点没有怀疑过,那些分割点是怎么求出来的,要提醒像我一样初写程序的朋友,一定要用数学的眼光去看算法问题,比如二分搜索里,我们在纸上画出一个线段,而这个线段的中分点,m的求法,真实的求法应该是m=l+(r-l)/2=(l+r)/2,依据这个思路,三分搜索,三分之一等分点应为m1=l+(r-l)*1/3=r/3+2*l/3,m2=l+(r-l)*2/3=2*r/3+l/3;我记得自己当初把这些重要的等分点求错,很大的原因是没有用数学的眼光去思考去看待,我只是在纸上画了一条线,而没有左右边界的概念,以及那个隐藏的零点概念,我想尽管有很多人不屑看到这里,我必须承认自己没有很多人聪明,但只要你从头再来一次,慢一点,重新出发,也许慢了一点,但至少坚持了下来,同样也希望给有帮助的人一点启示。
话不多说,上传代码,代码里,实现了二分查找,三分查找的递归以及非递归形式
#include<iostream>
#include<stdlib.h>
using namespace std;
int BinarySearch(int x,int a[],int left,int right)
{
int l= left;
int r=right;
while (l<=r)
{
int mid = (l+r)/2;
if(a[mid]==x) return mid;
else if(x>a[mid]) return BinarySearch(x,a,mid+1,r);
else if(x<a[mid])return BinarySearch(x,a,l,mid-1);
}
return -1;
}
int BinarySearch_2(int x,int a[],int left,int right)
{
int l= left;
int r=right;
while (l<=r)
{
int mid = (l+r)/2;
if(a[mid]==x) return mid;
else if(x>a[mid]) l=mid+1;
else if(x<a[mid])r=mid-1;
}
return -1;
}
int ThreeSearch(int x,int a[],int left,int right)
{
int l=left;
int r= right;
while(l<=r)
{
int m1=l+(r-l)*1/3;
int m2=l+(r-l)*2/3;
if(x==a[m1]) return m1;
if(x<a[m1]) r=m1-1;
if(x==a[m2]) return m2;
if(x>a[m2]) l=m2+1;
else if(x>a[m1]&&x<a[m2])
{
l=m1+1;
r=m2-1;
}
}
return -1;
}
int ThreeSearch_2(int x,int a[],int left,int right)
{
int l=left;
int r= right;
while(l<=r)
{
int m1=l+(r-l)*1/3;
int m2=l+(r-l)*2/3;
if(x==a[m1]) return m1;
if(x<a[m1]) return ThreeSearch_2(x,a,l,m1-1);
if(x==a[m2]) return m2;
if(x>a[m2]) return ThreeSearch_2(x,a,m2+1,r);
else if(x>a[m1]&&x<a[m2])
{
return ThreeSearch(x,a,m1+1,m2-1);
}
}
return -1;
}
int main()
{
int a[5]={1,2,3,4,5};
cout<<BinarySearch_2(4,a,0,4);
cout<<endl;
cout<<ThreeSearch(4,a,0,4);
system("pause");
}