ACM—二分查找

在有序表中高效查找元素的常用方法是二分查找,所谓二分即是折半,遵循分治的思想,每次将元序列划分成数量相等的两个子序列,然后查找,最终定位到目标元素。以下是代码(假设data序列按递增序排列):

int binary_search(int *data, int size, int value)
{
    int mid;
    int left = 0;
    int right = size - 1;
    while(left < right)
    {
        mid = left + (right-left)/2;              // 确保中点靠近区间的起点
        if(data[mid] == value) return mid;        //找到了
        else if(data[mid] > value) right = mid;   // 中间值较大,则查找值应在左半部分
        else left = mid + 1;                      //否则在右半部分
    }
    return -1;              //未找到,返回-1;
}

上述代码存在一个问题,就是当序列中存在多个value的时候,binary_search会返回最中间的那一个元素,有时候这不是我们想要的结果,换句话说这样就无法确定值等于value的完整区间,所以还需要对上面的代码进行改进,使得其可以查找出value出现的第一个位置和最后一个位置,其实就是对等于情况的讨论.

/*
该函数当value存在时返回它出现的第一个位置,
如果value不存在则返回位置i,满足在该位置插入value后该序列仍然有序
*/
int lower_bound(int *data, int size, int value)
{
    int mid;
    int left = 0;
    int right = size - 1;
    while(left < right)
    {
        mid = left + (right-left)/2;
        if(data[mid] >= value) right = mid; //这两句代码对比上面的其实只对有相同value的区间有影响
        else left = mid + 1;
    }
    return left;
}
/*
该函数当value存在时返回它出现的最后一个位置的后面一个位置,因为起点会移动到中点加一
如果value不存在则返回位置i,满足在该位置插入value后该序列仍然有序
*/
int upper_bound(int *data, int size, int value)
{
    int mid;
    int left = 0;
    int right = size - 1;
    while(left < right)
    {
        mid = left + (right-left)/2;
        if(data[mid] > value) right = mid; //这两句代码对比上面的其实只对有相同value的区间有影响,返回的是最后一个value的后一个位置
        else left = mid + 1;
    }
    return left;
}

所以,实现了前面两个函数,就可以使用它们来找出value的出现范围,假设lower_bound和upper_bound的返回值分别为L和R,那么value出现的子序列为[L,R),注意是前闭后开的一个区间,其实当value不存在时也成立,此时L等于R,即区间为空。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值