二分查找

使用二分查找的前提;所查找的部分一定要具有单调性;
二分查找的理论;
折半查找法也称为二分查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(log n)完成搜索任务。它的基本思想是,将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的x作比较,
如果x=a[n/2]则找到x,算法终止。
如果x《a[n/2],则我们只要在数组a的左半部继续搜索x,这里假设数组元素呈升序排列)。
如果x>a[n/2],则我们只要在数组a的右 半部继续搜索x。

1;二分查找之数组;
已知一个数组利用二分查找找到某个元素的下标;

#include<stdio.h>
int ef(int*a,int len, int t)//查找的函数
{
    int st = 0;
    int end = len-1;
    int mid ; 
    **while(st <= end){//跳出循环的条件
        mid = (end -st)/2+st;//防止 (end +st)越界
        if(a[mid] == t){//这个if结构是关键
            return mid;
        }
        else if(a[mid] > t){
            end = mid-1;
        }
        else st = mid+1;
    }** 
    return -1;//没有找到这个元素
}
int main()
{
    int m;
    int a[10]={1,2,3,4,5,6,7,8,9,10};
    m = ef(a,10,8);//在数组a[10]中找元素8的位置; 
    printf("%d\n",m);

    return 0 ;
} 

2;对函数二分查找;
就是解方程,保证精确度;
HDOJ-2199
给出方程:
8*x4 + 7*x3 + 2*x2 + 3*x + 6 = Y
其中,实数Y满足 (fabs(Y) <= 1e10)
输入Y
请输出x在区间[0,100]的解,结果精确到小数点后4位。

#include<stdio.h>
double f(double x)
{
    double y;
    y = 8*x*x*x*x+7*x*x*x+2*x*x+3*x+6;
    return y;
}
int main()
{
    int n;
    double y,st,end, mid;
    scanf("%d",&n);
    while(n--){
        scanf("%lf",&y);
        if(f(0)<=y&&y<=f(100)){ 
            st = 0;
            end = 100;
            while(end - st > 1e-7){//1e-7是精度问题; 
                mid = (end-st)/2+st;
                if(f(mid) > y){
                    end = mid-1e-7;
                }
                else
                    st = mid + 1e-7;
            }       
            printf("%.4lf\n",(end-st)/2+st); 
        }
        else     printf("No solution!\n");
    } 

    return 0 ;
} 

上面的1e-7次是保证精确度问题,一般取1e-7就好了;

3;二分查找对方程的导数二分查找;
HDOJ-2899
给出函数:
F(x) = 6*x7 + 8*x6 + 7*x3 + 5*x2 - y*x
其中,实数y满足 (0

#include<stdio.h>
#include<math.h>
double y;
double ds(double x)//导函数是单调递增的函数; 
{
    return 42.0*pow(x,6.0)+48.0*pow(x,5.0)+21.0*pow(x,2.0)+10.0*x-y;
} 
double hs(double x)
{
    return 6.0*pow(x,7.0)+8.0*pow(x,6.0)+7.0*pow(x,3.0)+5.0*pow(x,2.0)-y*x;
}
int main()
{
    int n;
    double st,end,mid;
    scanf("%d",&n);
    while(n--){
        scanf("%lf",&y);
        if(ds(100)<0){//导数的最大值都小于0则他就是最小值了 
            printf("%.4lf\n",hs(100));
            continue;
        }
        if(ds(0)>0){
            printf("%.4lf\n",hs(0));
            continue;
        }
        st = 0;
        end = 100;
        while(end-st>1e-8){//这里的精度是????? 
            mid = (end-st)/2+st;
            if(ds(mid)<0){//导数小于0则说明最小值在中间到后面那部分 
                st = mid;
            }
            else{
                end = mid;
            }
        }
        printf("%.4lf\n",hs(mid));
    }

    return 0 ;
} 

4;
4.1二分查找使用的关键在于;
被查找的一定要具有单调性;
4.2二分查找代码实现的关键在于
while条件和if判断与折中;

while(end-st>1e-8){//保证精确度一般取1e-7左右;
            mid = (end-st)/2+st;
            if(ds(mid)<0){//导数小于0则说明最小值在中间到后面那部分 
                st = mid;
            }
            else{
                end = mid;
            }
        }
while(end - st > 1e-7){//1e-7是精度问题; 
                mid = (end-st)/2+st;
                if(f(mid) > y){
                    end = mid-1e-7;
                }
                else
                    st = mid + 1e-7;
            }

看几个样例应该有点感觉了吧;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值