STL provides binary search functions std::lower_bound and std::upper_bound, but I tend not to use them because I\'ve been unable to remember what they do, because their contract
Both functions are very similar, in that they will find an insertion point in a sorted sequence that will preserve the sort. If there are no existing elements in the sequence that are equal to the search item, they will return the same iterator.
If you're trying to find something in the sequence, use lower_bound
- it will point directly to the element if it's found.
If you're inserting into the sequence, use upper_bound
- it preserves the original ordering of duplicates.
std::lower_bound
Returns an iterator pointing to the first element in the range [first, last) that is not less than (i.e. greater or equal to) value.
std::upper_bound
Returns an iterator pointing to the first element in the range [first, last) that is greater than value.
So by mixing both lower and upper bound you are able to exactly describe where your range begins and where it ends.
Does this make any sense??
Yes.
Example:
imagine vector
std::vector<int> data = { 1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6 };
auto lower = std::lower_bound(data.begin(), data.end(), 4);
1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6
// ^ lower
auto upper = std::upper_bound(data.begin(), data.end(), 4);
1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6
// ^ upper
std::copy(lower, upper, std::ostream_iterator<int>(std::cout, " "));
prints: 4 4 4
http://en.cppreference.com/w/cpp/algorithm/lower_bound
http://en.cppreference.com/w/cpp/algorithm/upper_bound
Imagine what you would do if you want to find the first element equal to val
in [first, last)
. You first exclude from first elements which are strictly smaller than val
, then exclude backward from last - 1 those strictly greater than val
. Then the remaining range is [lower_bound, upper_bound]
If you have multiple elements in the range [first
, last
) whose value equals the value val
you are searching for, then the range [l
, u
) where
l = std::lower_bound(first, last, val)
u = std::upper_bound(first, last, val)
is precisely the range of elements equal to val
within the range [first
, last
). So l
and u
are the "lower bound" and "upper bound" for the equal range. It makes sense if you're accustomed to thinking in terms of half-open intervals.
(Note that std::equal_range
will return both the lower and upper bound in a pair, in a single call.)