The lower and upper bounds of the binary search are the lowest and highest positions where the value can be inserted without disturbing the order. (In the C ++ standard library, these boundaries will be represented by iterators referring to an element in front of which a value can be inserted, but the concept has not been substantially changed.)
Take, for example, a sorted range
1 2 3 4 5 5 5 6 7 9
In binary search 3 we will have
v
And in binary search 5 :
v
The lower and upper borders are the same if the element does not exist in the range. In binary search 8 :
v
The author of the article you are referring to says all this in equivalent terms “less” and “more”, so that when searching for 5,
v
In all these cases, C ++ iterators refer to an element immediately abroad. I.e:
- In search
3 iterator returned by std::lower_bound will refer to 3 , and one of std::upper_bound will refer to 4 - In search
5 iterator returned by std::lower_bound will refer to the first 5 , and one of std::upper_bound will refer to 6 - In search
8 both will refer to 9
This is because the convention in the C ++ standard library for insertion is to pass an iterator that references the element before which the new element should be inserted. For example, after
std::vector<int> vec { 1, 3, 4, 5, 5, 5, 6, 7, 9 }; vec.insert(vec.begin() + 1, 2);
vec will contain 1, 2, 3, 4, 5, 5, 5, 6, 7, 9 . std::lower_bound and std::upper_bound follow this convention to
vec.insert(std::lower_bound(vec.begin(), vec.end(), 5), 5); vec.insert(std::upper_bound(vec.begin(), vec.end(), 8), 8);
work as desired and leave vec sorted.
In general, this is an expression of how ranges are defined in the C ++ standard library. The start iterator of the range refers to the first element of the range (if any), while the end iterator refers to the element (if any) immediately after the end of the range. Another way to look at this is that the iterators returned by std::lower_bound and std::upper_bound cover the range of elements in the search range that are equivalent to the element to be searched.
This range is empty if the element is not in the range, therefore lower_bound and upper_bound return the same iterator, otherwise lower_bound returns an iterator, referring to the first element in the search range, which is equivalent to the search value, and upper_bound returns an iterator referring to an element (if any) that immediately follows the last such element.