STL之lower_bound和upper_bound

本文详细介绍了二分查找算法的实现原理及其在C++标准模板库中的应用,包括lower_bound和upper_bound函数的具体实现过程,并通过实例展示了如何使用这些函数进行有效的搜索。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// Binary search (lower_bound, upper_bound, equal_range, binary_search).

template <class _ForwardIter, class _Tp, class _Distance>
_ForwardIter __lower_bound(_ForwardIter __first, _ForwardIter __last,
                           const _Tp& __val, _Distance*) 
{
  _Distance __len = 0;
  distance(__first, __last, __len);//求取整个区间的长度len
  _Distance __half;
  _ForwardIter __middle;//定义区间的中间迭代器

  while (__len > 0) {//若区间不为空,则在区间[first,last)开始查找value值
    __half = __len >> 1;//向右移一位,相当于除以2,即取区间的中间值
    __middle = __first;//middle初始化为区间的起始位置
    advance(__middle, __half);//middle向后移half位,此时middle为区间的中间值
    if (*__middle < __val) {//将value值与中间值比较,即是二分查找,若中间值小于value,则继续查找右半部分
		//下面两行令first指向middle的下一个位置
      __first = __middle;
      ++__first;
      __len = __len - __half - 1;//调整查找区间的长度
    }
    else
      __len = __half;//否则查找左半部分
  }
  return __first;
}
//在已排序区间[first,last)查找value值
//若该区间存在与value相等的元素,则返回指向第一个与value相等的迭代器
//若该区间不存在与value相等的元素,则返回指向第一个不小于value值的迭代器
//若该区间的任何元素都比value值小,则返回last
/*
函数功能:Returns an iterator pointing to the first element in the range [first,last) which does not compare less than val.
函数原型:
default (1)	:版本一采用operator<比较
	template <class ForwardIterator, class T>
	ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,
                               const T& val);
custom (2)	:版本二采用仿函数comp比较规则
	template <class ForwardIterator, class T, class Compare>
	ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,
                               const T& val, Compare comp);
*/
//版本一
template <class _ForwardIter, class _Tp>
inline _ForwardIter lower_bound(_ForwardIter __first, _ForwardIter __last,
				const _Tp& __val) {
  __STL_REQUIRES(_ForwardIter, _ForwardIterator);
  __STL_REQUIRES_SAME_TYPE(_Tp,
      typename iterator_traits<_ForwardIter>::value_type);
  __STL_REQUIRES(_Tp, _LessThanComparable);
  return __lower_bound(__first, __last, __val,
                       __DISTANCE_TYPE(__first));
}

template <class _ForwardIter, class _Tp, class _Compare, class _Distance>
_ForwardIter __lower_bound(_ForwardIter __first, _ForwardIter __last,
                              const _Tp& __val, _Compare __comp, _Distance*)
{
  _Distance __len = 0;
  distance(__first, __last, __len);//求取整个区间的长度len
  _Distance __half;
  _ForwardIter __middle;//定义区间的中间迭代器

  while (__len > 0) {//若区间不为空,则在区间[first,last)开始查找value值
    __half = __len >> 1;//向右移一位,相当于除以2,即取区间的中间值
    __middle = __first;//middle初始化为区间的起始位置
    advance(__middle, __half);//middle向后移half位,此时middle为区间的中间值
    if (__comp(*__middle, __val)) {//若comp判断为true,则继续在右半部分查找
		//下面两行令first指向middle的下一个位置
      __first = __middle;
      ++__first;
      __len = __len - __half - 1;//调整查找区间的长度
    }
    else
      __len = __half;//否则查找左半部分
  }
  return __first;
}
//版本二:
template <class _ForwardIter, class _Tp, class _Compare>
inline _ForwardIter lower_bound(_ForwardIter __first, _ForwardIter __last,
                                const _Tp& __val, _Compare __comp) {
  __STL_REQUIRES(_ForwardIter, _ForwardIterator);
  __STL_REQUIRES_SAME_TYPE(_Tp,
      typename iterator_traits<_ForwardIter>::value_type);
  __STL_BINARY_FUNCTION_CHECK(_Compare, bool, _Tp, _Tp);
  return __lower_bound(__first, __last, __val, __comp,
                       __DISTANCE_TYPE(__first));
}

template <class _ForwardIter, class _Tp, class _Distance>
_ForwardIter __upper_bound(_ForwardIter __first, _ForwardIter __last,
                           const _Tp& __val, _Distance*)
{
  _Distance __len = 0;
  distance(__first, __last, __len);//求取整个区间的长度len
  _Distance __half;
  _ForwardIter __middle;//定义区间的中间迭代器

  while (__len > 0) {//若区间不为空,则在区间[first,last)开始查找value值
    __half = __len >> 1;//向右移一位,相当于除以2,即取区间的中间值
    __middle = __first;//middle初始化为区间的起始位置
    advance(__middle, __half);//middle向后移half位,此时middle为区间的中间值
    if (__val < *__middle)//若value小于中间元素值
      __len = __half;//查找左半部分
    else {
		//下面两行令first指向middle的下一个位置
      __first = __middle;
      ++__first;
      __len = __len - __half - 1;//更新len的值
    }
  }
  return __first;
}
//在已排序区间[first,last)查找value值
//返回大于value值的第一个元素的迭代器
/*
函数功能:Returns an iterator pointing to the first element in the range [first,last) which compares greater than val.
函数原型:
default (1)	:版本一采用operator<比较
	template <class ForwardIterator, class T>
	ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last,
                               const T& val);
custom (2)	:版本二采用仿函数comp比较规则
	template <class ForwardIterator, class T, class Compare>
	ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last,
                               const T& val, Compare comp);
*/
//版本一
template <class _ForwardIter, class _Tp>
inline _ForwardIter upper_bound(_ForwardIter __first, _ForwardIter __last,
                                const _Tp& __val) {
  __STL_REQUIRES(_ForwardIter, _ForwardIterator);
  __STL_REQUIRES_SAME_TYPE(_Tp,
      typename iterator_traits<_ForwardIter>::value_type);
  __STL_REQUIRES(_Tp, _LessThanComparable);
  return __upper_bound(__first, __last, __val,
                       __DISTANCE_TYPE(__first));
}

template <class _ForwardIter, class _Tp, class _Compare, class _Distance>
_ForwardIter __upper_bound(_ForwardIter __first, _ForwardIter __last,
                           const _Tp& __val, _Compare __comp, _Distance*)
{
  _Distance __len = 0;
  distance(__first, __last, __len);
  _Distance __half;
  _ForwardIter __middle;

  while (__len > 0) {
    __half = __len >> 1;
    __middle = __first;
    advance(__middle, __half);
    if (__comp(__val, *__middle))
      __len = __half;
    else {
      __first = __middle;
      ++__first;
      __len = __len - __half - 1;
    }
  }
  return __first;
}
//版本二
template <class _ForwardIter, class _Tp, class _Compare>
inline _ForwardIter upper_bound(_ForwardIter __first, _ForwardIter __last,
                                const _Tp& __val, _Compare __comp) {
  __STL_REQUIRES(_ForwardIter, _ForwardIterator);
  __STL_REQUIRES_SAME_TYPE(_Tp,
      typename iterator_traits<_ForwardIter>::value_type);
  __STL_BINARY_FUNCTION_CHECK(_Compare, bool, _Tp, _Tp);
  return __upper_bound(__first, __last, __val, __comp,
                       __DISTANCE_TYPE(__first));
}
//函数举例
/*
	#include <iostream>     // std::cout
	#include <algorithm>    // std::lower_bound, std::upper_bound, std::sort
	#include <vector>       // std::vector

	int main () {
	  int myints[] = {10,20,30,30,20,10,10,20};
	  std::vector<int> v(myints,myints+8);           // 10 20 30 30 20 10 10 20

	  std::sort (v.begin(), v.end());                // 10 10 10 20 20 20 30 30

	  std::vector<int>::iterator low,up;
	  low=std::lower_bound (v.begin(), v.end(), 20); //          ^
	  up= std::upper_bound (v.begin(), v.end(), 20); //                   ^

	  std::cout << "lower_bound at position " << (low- v.begin()) << '\n';
	  std::cout << "upper_bound at position " << (up - v.begin()) << '\n';

	  return 0;
	}
	Output:
	lower_bound at position 3
	upper_bound at position 6
*/

<think>好的,我现在需要帮助用户了解C++ STLlower_boundupper_bound的用法。用户可能已经接触过mapset这些容器,但不太清楚这两个函数的区别应用场景。首先,我得回顾一下这两个函数的基本定义用途。 根据用户提供的引用资料,特别是引用34,里面提到了upper_bound的用法示例,比如在set中使用upper_bound查找第一个大于key的元素。但用户现在想同时了解lower_boundupper_bound,所以我需要详细解释两者的区别。 首先,lower_bound返回的是第一个大于或等于目标值的元素位置,而upper_bound返回的是第一个大于目标值的元素位置。这在有序容器中非常有用,比如在排序数组、vector、set或map中。这两个函数常用于确定插入位置或者查找元素范围。 接下来,我需要考虑用户可能的实际应用场景。比如在有序区间内插入元素时,可以用lower_bound找到合适的插入点;或者在处理范围查询时,比如统计某个区间内的元素数量,可以用这两个函数确定上下界。例如,用户可能想在一个已排序的vector中找到所有大于等于5且小于10的元素,这时候lower_bound(5)upper_bound(10)就能确定这个区间。 然后,我需要检查用户提供的引用内容是否有相关例子或代码片段。引用3中提到了upper_bound的使用方法,引用4展示了erasefind的结合使用。虽然这些例子没有直接展示lower_bound,但可以结合这些例子来说明两者的区别。例如,在set中,使用lower_bound找到第一个不小于key的元素,而upper_bound则是第一个大于key的,这样在删除某个范围的元素时,可以配合使用这两个函数。 还需要注意这两个函数的时间复杂度,因为它们通常基于二分查找实现,时间复杂度为O(log n),适用于有序容器。但如果是无序结构,比如unordered_map,这两个函数可能不可用,这时候用户可能需要先对容器进行排序,或者使用其他数据结构。 另外,用户可能在处理需要频繁查找插入有序数据的场景中使用这些函数,比如维护一个实时更新的排行榜,或者处理时间序列数据。这时候正确使用lower_boundupper_bound可以提高效率。 最后,我需要确保回答结构清晰,分点说明两者的定义、使用场景、代码示例以及注意事项。同时,根据用户要求生成相关问题,比如它们的区别、应用实例或底层实现原理。这样用户能够全面理解并应用到实际编程中。</think>### C++ STLlower_boundupper_bound用法解析 #### 一、基础定义与核心差异 1. **lower_bound** 在**有序区间**中返回第一个**大于或等于目标值**的元素迭代器 数学表达式:查找第一个满足$val \geq key$的元素位置 2. **upper_bound** 在**有序区间**中返回第一个**大于目标值**的元素迭代器 数学表达式:查找第一个满足$val > key$的元素位置 ```cpp // 示例:查找有序数组中的范围 vector<int> arr = {1,3,5,7,9}; auto lower = lower_bound(arr.begin(), arr.end(), 5); // 指向5 auto upper = upper_bound(arr.begin(), arr.end(), 5); // 指向7 ``` #### 二、典型应用场景 1. **范围查询** ```cpp // 统计[5,8)区间内的元素数量 set<int> s = {1,3,5,7,9}; auto start = s.lower_bound(5); // 包含5 auto end = s.upper_bound(8); // 不包含8 int count = distance(start, end); // 返回2(5,7) ``` 2. **插入位置确定** ```cpp // 在有序vector中插入元素保持有序性 vector<string> words = {"apple", "banana"}; auto pos = lower_bound(words.begin(), words.end(), "cherry"); words.insert(pos, "cherry"); // 插入到正确位置 ``` 3. **区间删除** ```cpp // 删除所有大于等于3且小于6的元素(引用4的扩展) set<int> myset = {1,2,3,4,5}; myset.erase(myset.lower_bound(3), myset.upper_bound(5)); // 剩余元素:{1,2} ``` #### 三、重要注意事项 1. **容器必须有序** 这两个函数基于二分查找实现,时间复杂度为$O(\log n)$,仅适用于有序容器如`set/map`或已排序的`vector`[^2] 2. **自定义比较函数** ```cpp // 自定义结构体排序规则 struct Person { int age; string name; }; vector<Person> people; // 按年龄升序排列后查找 auto it = lower_bound(people.begin(), people.end(), [](const Person& p, int age){ return p.age < age; }); ``` 3. **返回值验证** 需要检查返回迭代器是否有效,避免越界访问: ```cpp if(lower != container.end()) { // 安全操作 } ``` #### 四、关联容器特例 在`set/map`中可直接调用成员函数: ```cpp set<int> s = {1,3,5}; auto it = s.lower_bound(2); // 返回指向3的迭代器 map<string, int> m; m["apple"] = 5; auto mit = m.upper_bound("app"); // 查找第一个key大于"app"的条目 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值