二分查找与STL中的lower_bound(),upper_bound(),binary_search()

摘录自《STL源码剖析》

lower_bound()

  lower_bound()是二分查找的一种,在已排序的区间[first,last)中寻找元素value。如果[first,last)中与value相等的元素,便返回一个迭代器,指向其中第一个元素。如果没有这样的元素存在,便返回“假设这样的元素存在时应该出现的位置”。也就是说,它返回一个迭代器,指向第一个“不小于value”的元素。如果value大于[first,last)内的任何一个元素,则返回last。
  可以说,lower_bound()的返回值是“在不破坏排序状态的原则下,可以插入value的第一个位置”。
  这里写图片描述
  
  该算法的实现如下

template <class ForwardIterator,class T>
inline ForwardIterator lower_bound(ForwardIterator first,ForwardIterator  last,const T& value)
{
    return _lower_bound(first,last,value,distance_type(first),iterator_category(first));
}

template <class ForwardIterator,class T,class Distance>
ForwardIterator _lower_bound(ForwardIterator first,ForwardIterator  last,const T& value,Distance*,forward_iterator_tag)
{
    Distance len = 0;
    distance(first,last,len);
    Distance half;
    ForwardIterator middle;

    while (len > 0)
    {
        half = len>>1;  //除以2
        middle = first;   //这行和下面的一行令middle指向中间位置
        advance(middle,half);

        if (*middle < value)
        {
            first = middle; //这行和下面的一行令first指向middle的下一位置
            ++first;
            len = len -half -1; //修正len,回头测试循环的结束条件
        }
        else
            len = half;
    }

    return first;
}

template <class RandomAccessIterator,class T,class Distance>
RandomAccessIterator _lower_bound(RandomAccessIterator first,RandomAccessIterator  last,const T& value,Distance*,forward_iterator_tag)
{
    Distance len = last - first; //计算区间的长度
    Distance half;
    RandomAccessIterator middle;

    while (len >0)
    {
        half = len >> 1;    //除以2
        middle = first + half; //令middle指向中间位置

        if (*middle < value)
        {
            first = middle +1; //这行和下面的一行令first指向middle的下一位置
            len = len -half -1; //修正len,回头测试循环的结束条件
        }
        else
            len = half;
    }

    return first;
}

upper_bound()

  与lower_bound()类似,它也是二分查找的一个版本,它试图在已排序的[first,last)中寻找value。更确切地说,它会返回“在不破坏顺序的情况下,可插入value的最后一个合适位置。”
  由于STL规范“区间圈定”时的起头和结尾并不对称,所以upper_bound与lower_bound的返回值意义大有不同。如果查找某值,而它的确出现在区间之内,则lower_bound返回的是一个指向该元素的迭代器。然而upper_bound返回的迭代器将指向该元素的下一位置。
  该算法的实现如下
  

template <class ForwardIterator,class T>
inline ForwardIterator upper_bound(ForwardIterator first,ForwardIterator  last,const T& value)
{
    return _upper_bound(first,last,value,distance_type(first),iterator_category(first));
}

template <class ForwardIterator,class T,class Distance>
ForwardIterator _upper_bound(ForwardIterator first,ForwardIterator  last,const T& value,Distance*,forward_iterator_tag)
{
    Distance len = 0;
    distance(first,last,len);
    Distance half;
    ForwardIterator middle;

    while (len > 0)
    {
        half = len>>1;  //除以2
        middle = first;   //这行和下面的一行令middle指向中间位置
        advance(middle,half);

        if (*middle <= value)
        {
            first = middle; //这行和下面的一行令first指向middle的下一位置
            ++first;
            len = len -half -1; //修正len,回头测试循环的结束条件
        }
        else
            len = half;
    }

    return first;
}

template <class RandomAccessIterator,class T,class Distance>
RandomAccessIterator _upper_bound(RandomAccessIterator first,RandomAccessIterator  last,const T& value,Distance*,forward_iterator_tag)
{
    Distance len = last - first; //计算区间的长度
    Distance half;
    RandomAccessIterator middle;

    while (len >0)
    {
        half = len >> 1;    //除以2
        middle = first + half; //令middle指向中间位置

        if (*middle <= value)
        {
            first = middle +1; //这行和下面的一行令first指向middle的下一位置
            len = len -half -1; //修正len,回头测试循环的结束条件
        }
        else
            len = half;
    }

    return first;
}

binary_search()

  binary_search试图在已排序的[first,last)中寻找元素value,如果[first,last)中有等于value的元素,便返回true,否则返回false。
  binary_search利用lower_bound先找出“假设value存在的话,应该出现的位置”,然后再对比该位置上的值是否是我们所需要查找的目标,并返回对比结果。
  

template <class ForwardIterator,class T>
inline ForwardIterator binary_search(ForwardIterator first,ForwardIterator  last,const T& value)
{
    ForwardIterator i = lower_bound(first,last,value);
    return i!=last && !(value <*i);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值