lower_bound() source code analysis

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 valto .

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 valequal and the last valnumber 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_valas 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 valto

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_boundbetween 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< *iternumber that satisfies .

At this point in the analysis, back to our question, how to find the last number less than or valequal and the last valnumber 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 valequal , or the last valnumber 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 valof !__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 valnumber 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 valthan

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 << " ";
    }
}

Guess you like

Origin blog.csdn.net/aiyolo/article/details/126426727