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

来源:互联网 发布:linux服务器面板 编辑:程序博客网 时间:2024/06/05 01:59

摘录自《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);}
0 0
原创粉丝点击