upper_bound in C++ (original) (raw)
upper_bound is a Standard Template Library (STL) function used to find the first element that is strictly greater than a given value in a sorted range. It is commonly used for efficient searching and range queries in sorted containers.
**Example: Basic Usage with Vector
C++ `
#include #include #include using namespace std;
int main() { vector v = {10, 20, 30, 40, 50};
// Finding upper bound for value 30 in vector v
cout << *upper_bound(v.begin(), v.end(), 30);
return 0;}
`
**Explanation:
- The vector is already sorted
- upper_bound(30) skips 10, 20, 30
- Returns iterator pointing to 40
- Dereferencing the iterator prints 40
Syntax
iterator upper_bound(iterator first, iterator last, const T& value);
Parameters
- **first: Iterator to the first element of the range
- **last: Iterator to one past the last element of the range
- **value: The value to compare against
- **comp (optional): Custom comparison function
Return Value
- Returns an iterator to the first element greater than value
- Returns last if no such element exists
**Note: The behavior of std::upper_bound() is undefined if the range is not sorted
The below examples demonstrate some of its common uses.
**Example 1: Find Upper Bound in an Array
C++ `
#include #include #include using namespace std;
int main() { int arr[5] = {10, 20, 30, 40, 50}; int n = sizeof(arr) / sizeof(arr[0]);
// Finding upper bound for value 30 in array arr
cout << *upper_bound(arr, arr + n, 30);
return 0;}
`
**Explanation: This code uses upper_bound() to find and print the first element in the sorted array that is strictly greater than 30, which is 40.
**Example 2: Use upper_bound() with Custom Comparator
C++ `
#include #include #include using namespace std;
bool comp(const string &a, const string &b) { return lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), [](char c1, char c2) { return tolower(c1) < tolower(c2); }); }
int main() { vector v = {"Apple", "banana", "Cherry", "date", "Elderberry"};
// Finding upper bound of "Avocado"
auto ub = upper_bound(v.begin(), v.end(), "Avocado", comp);
if (ub != v.end())
cout << *ub;
else
cout << "Upper bound not found!";
return 0;}
`
**Explanation: We need to use the custom comparator function to perform the case insensitive search as the default comparator treats the uppercase and lowercase differently.
**Example 3: Check for an Element in a Sorted Vector
C++ `
#include #include #include using namespace std;
int main() { vector v = {10, 20, 30, 40, 50}; int val = 40;
// Finding the upper bound
auto it = upper_bound(v.begin(), v.end(), val);
// Chekcing if val exists or not
if (it != v.begin() && *(--it) == val)
cout << val << " is found.";
else
cout << val << " is NOT found.";
return 0;}
`
**Explanation: upper_bound() returns the iterator just after the matching value; to check if the value exists, decrement the iterator and compare.
**Example 4: Count Elements Smaller and Larger than a Value
C++ `
#include #include #include using namespace std;
int main() { vector v = {10, 20, 30, 40, 50}; int val = 30;
// Finding the upper bound of val in v
auto ub = upper_bound(v.begin(), v.end(), val);
// Finding the number of smaller elements
cout << "No. of Smaller Elements: " << ub - v.begin() << endl;
// Finding the number of larger elements
cout << "No. of Larger Elements: " << v.end() - ub;
return 0;}
`
Output
No. of Smaller Elements: 3 No. of Larger Elements: 2
**Explanation: Counts elements based on the position returned by upper_bound().
Finding Upper Bound in a Set
It is recommended to use set::upper_bound() for set as sets do not have random access to its elements. So, the upper_bound() function have to increment it sequentially to find the middle element (part of binary search algorithm) each time leading to increased time complexity.
C++ `
#include #include #include using namespace std;
int main(){
set<int> s = {1, 2, 4, 4, 6, 8};
// Recommended: O(log n)
auto it1 = s.upper_bound(4);
if (it1 != s.end())
cout << "set::upper_bound -> " << *it1 << endl;
else
cout << "set::upper_bound -> Not found" << endl;
// Not recommended: O(n) for set
auto it2 = upper_bound(s.begin(), s.end(), 4);
if (it2 != s.end())
cout << "std::upper_bound -> " << *it2 << endl;
else
cout << "std::upper_bound -> Not found" << endl;
return 0;}
`
Output
set::upper_bound -> 6 std::upper_bound -> 6
**Explanation:
- set::upper_bound() uses the Red-Black Tree structure of set, giving O(log n) time complexity.
- std::upper_bound() cannot perform binary search efficiently on set because it lacks random-access iterators, resulting in O(n) traversal.
- Both return the same value, but performance differs significantly.