Algorithm Equal Range Function - C++ Programming Tutorial
C++ Course / STL Algorithm / Algorithm Equal Range Function

Algorithm Equal Range Function

BLUF: Mastering Algorithm Equal Range Function is a critical step in becoming a proficient C++ developer. This lesson provides a deep dive into the syntax, performance considerations, and real-world applications of this concept.
Key Performance Insight: Algorithm Equal Range Function

C++ is renowned for its efficiency. Learn how Algorithm Equal Range Function enables low-level control and high-performance computing in the tutorial below.

The equal_range function in C++ serves as a variant of binary search. Its purpose is to provide both the lower and upper bounds of the subrange containing all elements equal to val within the range [first, last).

Where sub range is defined by two iterators, one pointing to the first element that is not less than val and another pointing to the first element greater than val.

  • The first version uses operator < to compare the elements and the second version uses the given comparison function i.e. comp.
  • The range [first, last) must be partitioned with respect to comparison with val, i.e. it must satisfy all of the following conditions: partitioned with respect to element < val or comp(element, val) partitioned with respect to !(val < element) or !comp(val, element) for all elements, if element < val or comp(element, val) is true then !(val < element) or !comp(val, element) is also true.
  • partitioned with respect to element < val or comp(element, val)
  • partitioned with respect to !(val < element) or !comp(val, element)
  • for all elements, if element < val or comp(element, val) is true then !(val < element) or !comp(val, element) is also true.
  • Syntax

Example

default (1)      template <class ForwardIterator, class T>
                       pair<ForwardIterator,ForwardIterator>
                         equal_range (ForwardIterator first, ForwardIterator last, const T& val);

custom (2)     template <class ForwardIterator, class T, class Compare>
                      pair<ForwardIterator,ForwardIterator>
                       equal_range (ForwardIterator first, ForwardIterator last, const T& val,
                          Compare comp);

Parameter

A forward iterator that points to the initial element within the specified range intended for searching.

last: A forward iterator indicating the element that comes after the last element in the range intended for searching.

The ```

include <iostream>

include <vector>

include <algorithm>

using namespace std;

int main

{

int a = {2, 3, 5, 6, 7, 7, 7, 8, 9, 10};

vector<int> v(a, a+10);

cout <<"\nHere are the contents of v:\n";

for (vector<int>::size_type i=0; i<v.size; i++)

cout <<v.at(i)<<" ";

pair<vector<int>::iterator, vector<int>::iterator> bounds;

bounds = equal_range(v.begin, v.end, 3);

if (bounds.first != v.end)

cout <<"\nLower bound of 3 in v = "<<*bounds.first;

if (bounds.first != v.end)

cout <<"\nUpper bound of 3 in v = "<<*bounds.second;

bounds = equal_range(v.begin, v.end, 4);

if (bounds.first != v.end)

cout <<"\nLower bound of 4 in v = "<<*bounds.first;

if (bounds.first != v.end)

cout <<"\nUpper bound of 4 in v = "<<*bounds.second;

bounds = equal_range(v.begin, v.end, 5);

if (bounds.first != v.end)

cout <<"\nLower bound of 5 in v = "<<*bounds.first;

if (bounds.first != v.end)

cout <<"\nUpper bound of 5 in v = "<<*bounds.second;

bounds = equal_range(v.begin, v.end, 7);

if (bounds.first != v.end)

cout <<"\nLower bound of 7 in v = "<<*bounds.first;

cout <<"\nThis is the first of the three 7's, since the value "

"before this 7 is "<<*(bounds.first-1)<<".";

if (bounds.first != v.end)

cout <<"\nUpper bound of 7 in v = "<<*bounds.second;

bounds = equal_range(v.begin, v.end, 0);

if (bounds.first != v.end)

cout <<"\nLower bound of 0 in v = "<<*bounds.first;

if (bounds.first != v.end)

cout <<"\nUpper bound of 0 in v = "<<*bounds.second;

bounds = equal_range(v.begin, v.end, 15);

if (bounds.first != v.end)

cout <<"\nLower bound of 15 in v = "<<*bounds.first;

if (bounds.first != v.end)

cout <<"\nUpper bound of 15 in v = "<<*bounds.second;

cout <<"\nNote that both the lower and upper bound locations "

"\nof 15 are the end (one-past-the-last) vector position.";

return 0;

}

Example


val : An upper limit value used to compare the elements within the specified range.

## Return value

It provides a pair of iterators, where one indicates the initial element equal to or greater than val, and the other indicates the initial element greater than val.

If no such element is found then it returns last.

## Complexity

On average, the computational complexity increases logarithmically as the distance between the first and last elements grows: it can conduct a maximum of 2 times the logarithm base 2 of N, plus 1, element comparisons. Here, N represents the difference between the last and first elements.

## Data races

The elements within the range [first, last) are retrieved.

## Exceptions

This function will raise an exception if an exception is thrown during either an element comparison or an iterator operation.

Please be aware that using incorrect parameters can result in unpredictable behavior.

## Example 1

Let's explore a straightforward example to illustrate the implementation of equal_range():

include <iostream>

include <vector>

include <algorithm>

using namespace std;

int main

{

vector<int> v = {3, 1, 4, 2, 5};

sort(v.begin, v.end);

auto result = equal_range(v.begin, v.end, 3);

cout << "Lower Bound of 3 is: "<<*result.first << endl;

cout << "Upper Bound of 3 is: "<<*result.second << endl;

return 0;

}

Example


Output:

Lower Bound of 3 is: 3

Upper Bound of 3 is: 4

Example


## Example 2

Let's explore another straightforward example to contrast the elements by utilizing the operator<:

include <algorithm>

include <vector>

include <iostream>

using namespace std;

struct S

{

int number;

char name;

S ( int number, char name )

: number ( number ), name ( name )

{}

// only the number is relevant with this comparison

bool operator< ( const S& s ) const

{

return number < s.number;

}

};

int main

{

// note: not ordered, only partitioned w.r.t. S defined below

vector<S> vec = { {1,'A'}, {2,'B'}, {2,'C'}, {2,'D'}, {4,'G'}, {3,'F'} };

S value ( 2, '?' );

auto p = equal_range(vec.begin,vec.end,value);

for ( auto i = p.first; i != p.second; ++i )

cout << i->name << ' ';

return 0;

}

Example


Output:

In the example provided, the < operator is utilized to compare elements and retrieve all elements within the specified range that are equal to 2.

## Example 3

Let's examine another straightforward example to contrast the elements utilizing a comparison function:

include <algorithm>

include <vector>

include <iostream>

using namespace std;

struct S

{

int number;

char name;

S ( int number, char name )

: number ( number ), name ( name )

{}

// only the number is relevant with this comparison

bool operator< ( const S& s ) const

{

return number < s.number;

}

};

struct Comp

{

bool operator ( const S& s, int i )

{

return s.number < i;

}

bool operator ( int i, const S& s )

{

return i < s.number;

}

};

int main

{

// note: not ordered, only partitioned w.r.t. S defined below

vector<S> vec = { {1,'A'}, {2,'B'}, {2,'C'}, {2,'D'}, {4,'G'}, {3,'F'} };

auto p = equal_range(vec.begin,vec.end,2,Comp);

for ( auto i = p.first; i != p.second; ++i )

cout << i->name << ' ';

return 0;

}

Example


Output:

## Example 4

Let's see another simple example:

include <iostream>

include <vector>

include <algorithm>

using namespace std;

int main

{

int a = {2, 3, 5, 6, 7, 7, 7, 8, 9, 10};

vector<int> v(a, a+10);

cout <<"\nHere are the contents of v:\n";

for (vector<int>::size_type i=0; i<v.size; i++)

cout <<v.at(i)<<" ";

pair<vector<int>::iterator, vector<int>::iterator> bounds;

bounds = equal_range(v.begin, v.end, 3);

if (bounds.first != v.end)

cout <<"\nLower bound of 3 in v = "<<*bounds.first;

if (bounds.first != v.end)

cout <<"\nUpper bound of 3 in v = "<<*bounds.second;

bounds = equal_range(v.begin, v.end, 4);

if (bounds.first != v.end)

cout <<"\nLower bound of 4 in v = "<<*bounds.first;

if (bounds.first != v.end)

cout <<"\nUpper bound of 4 in v = "<<*bounds.second;

bounds = equal_range(v.begin, v.end, 5);

if (bounds.first != v.end)

cout <<"\nLower bound of 5 in v = "<<*bounds.first;

if (bounds.first != v.end)

cout <<"\nUpper bound of 5 in v = "<<*bounds.second;

bounds = equal_range(v.begin, v.end, 7);

if (bounds.first != v.end)

cout <<"\nLower bound of 7 in v = "<<*bounds.first;

cout <<"\nThis is the first of the three 7's, since the value "

"before this 7 is "<<*(bounds.first-1)<<".";

if (bounds.first != v.end)

cout <<"\nUpper bound of 7 in v = "<<*bounds.second;

bounds = equal_range(v.begin, v.end, 0);

if (bounds.first != v.end)

cout <<"\nLower bound of 0 in v = "<<*bounds.first;

if (bounds.first != v.end)

cout <<"\nUpper bound of 0 in v = "<<*bounds.second;

bounds = equal_range(v.begin, v.end, 15);

if (bounds.first != v.end)

cout <<"\nLower bound of 15 in v = "<<*bounds.first;

if (bounds.first != v.end)

cout <<"\nUpper bound of 15 in v = "<<*bounds.second;

cout <<"\nNote that both the lower and upper bound locations "

"\nof 15 are the end (one-past-the-last) vector position.";

return 0;

}

Example


Output:

Here are the contents of v:

2 3 5 6 7 7 7 8 9 10

Lower bound of 3 in v = 3

Upper bound of 3 in v = 5

Lower bound of 4 in v = 5

Upper bound of 4 in v = 5

Lower bound of 5 in v = 5

Upper bound of 5 in v = 6

Lower bound of 7 in v = 7

This is the first of the three 7's, since the value before this 7 is 6.

Upper bound of 7 in v = 8

Lower bound of 0 in v = 2

Upper bound of 0 in v = 2

Note that both the lower and upper bound locations

of 15 are the end (one-past-the-last) vector position.

Example


Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience