数据结构:二分查找的C++实现及细节分析

二分查找可能是最早接触的查找方式,时间复杂度仅为O(lg2(n))级别,而且易于理解

但是理解了是一回事,动手写起来又是一回事,绝大部分人会在是否取等以及边界值+1的问题上栽倒很多次,就像《只狼》拼刀,看通关视频都很容易,苇名一心也不过尔尔,结果自己打的时候上来就在新手村先死个20次

先附上原码:

int binary_search(vector<int>& nums, int target)//搜索后返回数据在数组的坐标值,如果不存在则返回-1
{
    int right=nums.size()-1;//二分查找的右极限
    int left=0;//二分查找的左极限
    int middle=left+(right-left)/2;//中间数的坐标
    int number=nums[middle];//中间的数据
    while(number!=target)
    {
        if(number>target)
        {
            right=middle;
            middle=left+(right-left)/2;
            number=nums[middle];
        }
        else if(number<target)
        {
            left=middle+1;
            middle=left+(right-left)/2;
            number=nums[middle];
        }
        if(right==left&&number!=target)
            return -1;
    }
    return middle;
}

接下来解释细节部分:

1.取等问题

很多人都在left和right比较大小的地方犹豫很久,这里我特意绕开了这个判断,直接在循环中省去了两者比较的判断,单独列出一个if作为判断条件:既然left和right已经取等,说明查找也到了最后一步,如果再没有合适的值,就直接退出即可

2.+1问题

这里是绝大部分人在第一次尝试的时候绝对会栽跟头的地方

由于计算机计算数据的时候采用2进制编码数据,对于无法整除数据的情况,采用的是“向0取整”,即:结果大于0的小数,仅保留整数部分,结果小于0的小数,采用进一的方式取整

由于数组的下标均为非负数,所以二分查找的平均数也一定为正数,因此,每次取整的时候,数据会偏小,也就是left会更新为一个较小的整数

例如:当面临要查找的数据恰好处于下标7上,此时left=6,right=7,每次对middle和left进行更新的时候,left都因为向下取整的问题而无限循环……

这时候,我们需要舍弃:既然之前,middle上的数据已经不是我们需要的了,那就让left在顶替middle的时候自动+1

但由于right没有向下取整的问题,所以不需要进行对应的-1操作,如果进行了-1操作,反而会出现新的问题:

例如,我们在数组[5]当中查找数字-2,此时left,middle,right均为0,在第一轮循环的时候,由于需要对right进行-1,这时就会出现数组下标负溢出的情况(right=-1)

3.细节问题

由于我们需要查找的数组可能会很大,大到下标即将溢出int型的范围,这时候我们就要小心了:middle在采用(right+left)/2的计算模式下, 可能会溢出

所以我们修改了middle的计算方式,将其改为一种较为安全的计算方法,保证计算的过程中,不会出现溢出的可能

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值