STL 中 lower_bound 与 upper_bound 与 二分查找

首先,先说明 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;
	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值