摘录自《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);
}