📅  最后修改于: 2023-12-03 14:39:50.610000             🧑  作者: Mango
lower_bound()
函数是C++ STL中的一个非常有用的函数,它可用于在有序的容器中查找某个元素的位置,或者用于查找第一个大于等于给定值的元素的位置。本文将介绍lower_bound()
函数的用法和其实现原理,希望能帮助读者更好地理解这个函数的作用和使用方法。
lower_bound()
函数的定义和用法lower_bound()
函数的定义如下所示:
template<class ForwardIt, class T>
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value);
lower_bound()
函数的参数说明如下:
first
和last
分别是容器迭代器的起始位置和结束位置。函数将在[first, last)
区间内查找。value
是要查找的值。该值必须与容器元素的类型兼容,并且容器中的元素必须是有序的。lower_bound()
函数的返回值是一个迭代器,它指向容器中第一个大于等于给定值的元素的位置。如果容器中没有大于等于给定值的元素,则返回一个指向last
的迭代器。
下面是lower_bound()
函数的一个简单例子:
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<int> vec = {1, 2, 3, 4, 4, 5, 6};
auto it = std::lower_bound(vec.begin(), vec.end(), 4);
if (it == vec.end()) {
std::cout << "4 is not found in vec\n";
} else {
std::cout << "4 is found at index " << std::distance(vec.begin(), it) << '\n';
}
return 0;
}
输出如下:
4 is found at index 3
lower_bound()
函数的实现原理lower_bound()
函数的实现原理是利用了二分查找算法,因为容器是有序的,所以可以通过不断地折半查找,最终找到第一个大于等于给定值的元素的位置。下面是lower_bound()
函数的一个简化版实现,用于查找整数数组中是否存在某个值:
int lower_bound(int arr[], int n, int x)
{
int l = 0, r = n - 1;
while (l < r) {
int mid = l + (r - l) / 2;
if (arr[mid] < x)
l = mid + 1;
else
r = mid;
}
if (arr[l] >= x)
return l;
else
return -1;
}
这里的arr
是整数数组,n
是数组的元素个数,x
是要查找的值。该函数的返回值是第一个大于等于x
的元素的位置,如果不存在,则返回-1
。
实际上,C++ STL中的lower_bound()
函数实现要更加复杂,它不仅支持随机访问迭代器,还支持双向迭代器和随机访问迭代器,具体如下:
template<class ForwardIt, class T>
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value)
{
using category = typename std::iterator_traits<ForwardIt>::iterator_category;
return __lower_bound(first, last, value, category());
}
// 辅助函数,用于随机访问迭代器
template<class RandomIt, class T>
RandomIt __lower_bound(RandomIt first, RandomIt last, const T& value, std::random_access_iterator_tag)
{
auto len = last - first;
auto half = len;
RandomIt middle;
while (len > 0) {
half = len >> 1;
middle = first + half;
if (*middle < value) {
first = middle + 1;
len = len - half - 1;
} else {
len = half;
}
}
return first;
}
// 辅助函数,用于双向迭代器
template<class BidirIt, class T>
BidirIt __lower_bound(BidirIt first, BidirIt last, const T& value, std::bidirectional_iterator_tag)
{
using rev_iter = std::reverse_iterator<BidirIt>;
return std::reverse_iterator<BidirIt>(
std::upper_bound(rev_iter(last), rev_iter(first), value)).base();
}
lower_bound()
函数的实现分为两个辅助函数,分别用于随机访问迭代器和双向迭代器。这里仅展示随机访问迭代器的实现方式,具体如下:
len
,然后利用二分查找算法,将区间折半查找。value
,则将左端点first
移动到中间元素的下一个位置,同时将剩余区间的长度减去一半。value
,则将右端点last
移动到中间元素的位置。first
的值。对于双向迭代器,由于没有随机访问的特性,因此不能像随机访问迭代器那样直接折半查找。另外,lower_bound()
函数仍然需要保证二分查找的正确性,因此可以利用upper_bound()
函数来实现。具体实现方式如下:
last
反向迭代器转换为reverse_iterator<BidirIt>
类型的迭代器,将first
转换为相应的类型。然后调用upper_bound()
函数。upper_bound()
函数可以在一个有序区间中查找第一个大于给定值的元素的位置。因此,我们可以将last
作为起始位置,first
作为结束位置进行查找,得到第一个大于value
的元素的位置。base()
函数转换为正向迭代器的形式,并返回。lower_bound()
函数是一个非常有用的函数,它可以用于在有序的容器中快速查找元素的位置。借助二分查找算法,lower_bound()
函数可以高效地查找第一个大于等于给定值的元素的位置,具有较高的时间复杂度和空间复杂度。同时,C++ STL中的lower_bound()
函数支持多种迭代器类型,具有很好的通用性和适应性。因此,在实际编程中,开发者可以充分利用lower_bound()
函数的特性,提高代码的效率和质量。