lower_bound()
You can use the dichotomy method to search for a certain number that satisfies the condition in the array. By default, it searches for the first number greater than or equal val
to .
For example, the following code will output 3;
vector<int> arr={1,3,5,7};
cout << *lower_bound(arr.begin(), arr.end(), 3); // 打印3
There is also a upper_bound()
function that lower_bound()
is very similar to , but by default it returns the first number in the array that is val
greater .
It is natural to think whether these two functions can be used to further find the last number less than or val
equal and the last val
number less than in the array.
For this reason, we analyze the source code lower_bound()
of .
First, lower_bound()
a lower-level function will be called __lower_bound()
. lower_bound()
The default comparison function is to return true when__iter_less_val()
the value of the iterator is less than . We can also define a comparison function by ourselves .val
__comp(iter, val)
lower_bound(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val, _Compare __comp)
{
return std::__lower_bound(__first, __last, __val,
__gnu_cxx::__ops::__iter_comp_val(__comp));
}
__lower_bound()
In , use the dichotomy method to search, and take the default comparison function __iter_less_val
as an example to illustrate
- If
*__middle < __val
, (__comp(__middle,val)
i.e. true), the left border shrinks to the right - If
*__middle >=__val
, (__comp(__middle,val)
i.e. false) the right border shrinks to the left
Since the last iterator returned is the left boundary iterator, the left iterator always satisfies condition 2, but not condition 1
So in general, lower_bound()
the best effect is to continuously shrink the right boundary to the left and find a value greater than or equal val
to
If the default comparison function is replaced by a general function __comp(iter,val)
, then lower_bound()
is equivalent to finding the first !comp(iter, val)
value of .
upper_bound()
The default comparison function is __val_less_iter()
, and you can also customize the comparison function __comp(val,iter)
. The difference lower_bound
between is mainly that val here is the first parameter.
upper_bound()
Returns the first number __comp(val, iter)
that , or if the default functor is used, returns the first val< *iter
number that satisfies .
At this point in the analysis, back to our question, how to find the last number less than or val
equal and the last val
number less than in the array?
Note that whether it is lower_bound()
or upper_bound()
, they will continue to shrink the boundary from right to left when the condition is met, and finally return the value of the left boundary. For lower_bound()
, this condition is !comp(iter,val)
, and upper_bound()
for , this condition is comp(val, iter)
.
To find the last number less than or val
equal , or the last val
number less than , obviously we need to keep shrinking the boundary from left to right when the less than or equal condition is met, and finally return the value of the right boundary.
In order to do this, reverse_iterator can be used!
The rest is to transform the condition val
of !__comp(iter,val)
, see the transformation method below
*iter<=val <====> !(iter>val) <=====> !greater(iter,val) <====> !greater<int>()
That is to say, as long as you use it greater<int>()
as a comparison function, you can find the last val
number in the array that is less than or equal to
In the same way upper_bound()
, with reverse_iterator and greater<int>()
can be used to find the last value less val
than
Finally a little test
int main(){
vector<int> arr = {
1,3,5,7,9,11,13,15};
cout << *lower_bound(arr.rbegin(), arr.rend(), 9, greater<int>()).<< endl; // 返回9
cout << *upper_bound(arr.rbegin(), arr.rend(), 9, greater<int>()) << endl; // 返回7
for(auto arr_it = arr.rbegin(); arr_it != arr.rend(); arr_it++){
cout << *arr_it << " ";
}
}