您的位置:首页 > 其它

STL 中 lower_bound 与 upper_bound 与 二分查找

2015-11-01 12:07 316 查看
首先,先说明 lower_bound 与 upper_bound 的含义。对于区间 [first,last) 内的元素:

1.lower_bound :寻找最远的 i,使得 [ first, i ) 中的每个迭代器 j 都满足 *j < value

2.upper_bound:寻找最远的 i,使得 [ first, i ) 中的每个迭代器 j 都不满足 *j > value

示例:

序列: 1,2,3,5,6

3 的 lower_bound : 3。3 的 upper_bound : 5

4 的 lower_bound : 5。4 的 upper_bound : 5

实现:

使用二分查找法找到对应的位置,重点是 lower_bound 与 upper_bound 判断之间的区别,lower_bound 要找到第一个不小于 value 的元素因此将所有小于等于 value
的值划分到左区间
upper_bound 要找到第一个大于 value 的值,因此将所有大于等于 value 的值划分到右区间。注意划分左右区间时,刚好抹去了中间的元素。这是为了避免死循环。具体代码如下:

1.lower_bound:

template<class RandomAccessIterator,class T,class Distance>
	RandomAccessIterator __lower_bound(RandomAccessterator first, RandomAccessIterator last, const T& value, Distance*, random_access_iterator_tag)
	{
		Distance len = _LXX::distance(first, last);
		Distance half;
		RandomAccessIterator middle;

		while (len > 0)
		{
			half = len >> 1;
			middle = first + half;
			if (*middle < value)  //*middle < value, 所找的值一定在右半部分
			{
				first = ++middle;
				len = len - half - 1;
			}
			else //*middle >= value, 所找的值在左半部分或者在 middle 处
				len = half;  //此处若是写为 len = half + 1, 则当 value == middle, len = 0 时将进入死循环
		}
		return first;
	}


*注意二分区间的划分:左区间:len = half,右区间:len = len - half - 1 ,(half = len >> 1),其中左右区间划分不包含中间元素(len_left + len_right = len - 1),但是当 中间元素 == value 时,左区间中若还有 value,则忽略中间元素不会影响结果;若左区间中无
value,则二分查找会找回到中间元素的前一个元素,又因为前一个元素小于中间元素,则会更新 first = ++middle,即返回超出区间的下一个元素(左区间的下一个元素即是中间元素)。因此,忽略中间元素仍然能找回来。

2.upper_bound:

template<class RandomAccessIterator, class T, class Distance>
	RandomAccessIterator __upper_bound(RandomAccessIterator first, RandomAccessIterator last, const T &value, Distance *,random_access_iterator_tag)
	{
		Distance len = _LXX::distance(first, last);
		RandomAccessIterator middle;
		Distance half = 0;

		while (len > 0)
		{
			half = len >> 1;
			middle = first + half;

			if (value < *middle)
			{
				len = half;
			}
			else
			{
				first = middle + 1;
				len = len - half - 1;
			}
		}
		return first;
	}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: