二分法详解

概念

        何谓折半查找,举个例子很快就可以明白,给你了9个数 1 2 3 4 5 6 7 8 9 让你去找2在哪里,这时候你肯定会说这太简单了,但是计算机就没那么强了,它得拿着2和这9个数一个一个的比较,2在前面还好比较的次数比较小,但是如果让你找6在哪呢,需要比较的次数就多了,可能你觉得多这一次两次没什么差别,但是如果1到10000个数让你找呢,这时候折半查找的优势就显现出来了。我们先看2在不在1-5里面也就是前半段,如果在前半段,我们直接不和后边的数进行比较,我们确定2在1到5里面之后,我们再用类似的办法再去掉一半,看2在不在1到3面里,如果不在我们去3到5里找,如此下去直到找到为止,我们会发现计算机最擅长干的事就是迭代,而优秀的算法就是让计算机迭代的次数少一点。

        参考:谭浩强程序设计

应用场景

1 当要求时间复杂度为o(nlogn)的时候一般需要采用二分法

2 当数组部分有序或者完全有序需要采用二分法

注意事项

在使用二分法的时候需要考虑到边界问题。通常来说有两种写法,一种是左闭右闭区间,一种是左闭右开,具体选择哪种取决于具体的需求。

左闭右闭

  • while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
  • if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1

左闭右开

  • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
  • if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]

代码实现

c++代码实现

#include<iostream>
using namespace std;
int main()
{
    const int n=10;
    int i,number,top,bott,mid,loca,a[n];//mid用bott和top表示,方便迭代。
    bool flag=true,sign;//设置布尔变量即标志位。
    char c;
    cout<<"enter data:"<<endl;
    cin>>a[0];
    i=1;
    while(i<n)
    {
        cin>>a[i];
        if(a[i]>=a[i-1])
            i++;
        else
            cout<<"enter this data again:";//输入已经排好序的数列,也可以加上冒泡排序自动排序
    }
    cout<<endl;
    for(i=0;i<n;i++)
        cout<<a[i]<<" ";
        cout<<endl;
        while(flag)
        {
            cout<<"input number of to look for:";
            cin>>number;
            sign=false;
            top=0;
            bott=n-1;
            if((number<a[0])||(number>a[n-1]))
            loca=-1;
            while((!sign)&&(top<=bott))
                {
                    mid=(bott+top)/2;
                    if(number==a[mid])
                        {
                        	loca=mid;
                            cout<<"find"<<number<<",its position is"<<loca+1<<endl;
                            sign=true;
                        }
                    else if(number<a[mid])
                            bott=mid-1;//舍去后一半
                    else
                        top=mid+1;
                }
            if(!sign||loca==-1)
                   cout<<number<<"has not found"<<endl;
                   cout<<"continue or not";
                   cin>>c;
                   if(c=='n'||c=='N')
                    flag=false;
        }
            return 0;
}

输入十个已经排好序的数,然后进行查找。

  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值