Skip to content
Laviyx Learn

Try

C++ course menu

C++ STL Algorithms: sort, find, count, accumulate, transform and More

Learn the most useful C++ <algorithm> and <numeric> functions: sort with custom comparators, stable_sort, find and find_if, count_if, any_of/all_of, min_element and max_element, accumulate, transform, remove_if with erase, binary_search, reverse, unique, and C++20 ranges.

Intermediate14 min readUpdated
On this page

The headers <algorithm> and <numeric> contain more than a hundred ready-made functions for sorting, searching, counting and transforming data. They are well tested, usually faster than hand-written loops, and they make your intent obvious: std::count_if says "count" far more clearly than a loop with a counter.

Most algorithms take a range as two iterators (begin, end), and many take a function, usually a short lambda, that says what to do with each element. Lambdas are covered fully in Lambdas; here you only need the basic form [](int x) { return x > 0; }.

Sorting#

C++
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

void print(const std::vector<int>& v) {
    for (int x : v) std::cout << x << ' ';
    std::cout << '\n';
}

int main() {
    std::vector<int> v = {42, 7, 19, 3, 25};

    std::sort(v.begin(), v.end());
    print(v);

    std::sort(v.begin(), v.end(), std::greater<int>());   // descending
    print(v);
}
Output
3 7 19 25 42
42 25 19 7 3

Sorting with a custom rule#

Pass a comparator that returns true when the first argument should come before the second:

C++
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

struct Student {
    std::string name;
    int marks;
};

int main() {
    std::vector<Student> students = {{"Ravi", 85}, {"Asha", 92}, {"Meera", 85}, {"John", 78}};

    std::sort(students.begin(), students.end(), [](const Student& a, const Student& b) {
        if (a.marks != b.marks) return a.marks > b.marks;   // higher marks first
        return a.name < b.name;                             // then by name
    });

    for (const auto& s : students) std::cout << s.name << ' ' << s.marks << '\n';
}
Output
Asha 92
Meera 85
Ravi 85
John 78

std::sort is O(n log n) but not stable: equal elements may change order. std::stable_sort keeps equal elements in their original order, which matters when sorting by one key after another.

Searching#

C++
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {4, 9, -2, 7, -5, 12};

    auto it = std::find(v.begin(), v.end(), 7);
    std::cout << "7 at index " << (it - v.begin()) << '\n';

    auto neg = std::find_if(v.begin(), v.end(), [](int x) { return x < 0; });
    if (neg != v.end()) std::cout << "first negative: " << *neg << '\n';

    std::cout << std::boolalpha;
    std::cout << std::any_of(v.begin(), v.end(), [](int x) { return x > 10; }) << ' '
              << std::all_of(v.begin(), v.end(), [](int x) { return x > -10; }) << ' '
              << std::none_of(v.begin(), v.end(), [](int x) { return x == 0; }) << '\n';
}
Output
7 at index 3
first negative: -2
true true true

Binary search on sorted data#

On a sorted range, std::binary_search checks membership in O(log n), and std::lower_bound finds where a value is (or would be inserted):

C++
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> sorted = {3, 8, 15, 23, 42, 57};

    std::cout << std::boolalpha << std::binary_search(sorted.begin(), sorted.end(), 23) << '\n';

    auto pos = std::lower_bound(sorted.begin(), sorted.end(), 20);
    std::cout << "20 would go at index " << (pos - sorted.begin()) << ", before " << *pos << '\n';
}
Output
true
20 would go at index 3, before 23

Counting, minimum and maximum#

C++
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> marks = {56, 91, 78, 34, 88, 91};

    std::cout << std::count(marks.begin(), marks.end(), 91) << '\n';
    std::cout << std::count_if(marks.begin(), marks.end(), [](int m) { return m >= 75; }) << '\n';

    auto [lo, hi] = std::minmax_element(marks.begin(), marks.end());
    std::cout << "lowest " << *lo << ", highest " << *hi << '\n';
    std::cout << "best at index " << (std::max_element(marks.begin(), marks.end()) - marks.begin()) << '\n';
}
Output
2
4
lowest 34, highest 91
best at index 1

max_element returns an iterator to the first largest element. For just two or three values, use std::max(a, b) or std::min({a, b, c}).

Summing and combining: <numeric>#

C++
#include <iostream>
#include <numeric>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    int sum = std::accumulate(v.begin(), v.end(), 0);
    long long product = std::accumulate(v.begin(), v.end(), 1LL, [](long long acc, int x) { return acc * x; });

    std::vector<int> ids(5);
    std::iota(ids.begin(), ids.end(), 101);   // 101, 102, 103, ...

    std::cout << sum << ' ' << product << ' ' << ids.front() << ".." << ids.back() << '\n';
}
Output
15 120 101..105

Transforming#

std::transform applies a function to each element and writes the results, possibly into the same container:

C++
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<double> prices = {100, 250, 80};
    std::vector<double> with_tax(prices.size());
    std::transform(prices.begin(), prices.end(), with_tax.begin(), [](double p) { return p * 1.18; });

    for (double p : with_tax) std::cout << p << ' ';
    std::cout << '\n';

    std::string s = "Hello";
    std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::toupper(c); });
    std::cout << s << '\n';
}
Output
118 295 94.4
HELLO

Removing elements#

std::remove_if does not shrink the container: it moves the kept elements to the front and returns where the "garbage" tail starts. Pair it with erase (the erase-remove idiom), or use C++20's std::erase_if, which does both:

C++
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> a = {5, -2, 8, -7, 3};
    a.erase(std::remove_if(a.begin(), a.end(), [](int x) { return x < 0; }), a.end());

    std::vector<int> b = {5, -2, 8, -7, 3};
    std::erase_if(b, [](int x) { return x < 0; });   // C++20

    for (int x : a) std::cout << x << ' ';
    std::cout << "| ";
    for (int x : b) std::cout << x << ' ';
    std::cout << '\n';
}
Output
5 8 3 | 5 8 3

Reverse, unique and more#

C++
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {3, 1, 3, 2, 1, 3};

    std::sort(v.begin(), v.end());                       // 1 1 2 3 3 3
    v.erase(std::unique(v.begin(), v.end()), v.end());   // remove adjacent duplicates
    std::reverse(v.begin(), v.end());

    for (int x : v) std::cout << x << ' ';
    std::cout << '\n';
}
Output
3 2 1

std::unique removes only adjacent duplicates, so sort first. Other useful algorithms: std::fill, std::copy, std::rotate, std::shuffle, std::partition, std::nth_element, and std::next_permutation.

C++20 ranges#

C++20 adds versions of the algorithms in the std::ranges namespace that take a whole container instead of two iterators, plus views that filter and transform lazily:

C++
#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> v = {5, 2, 8, 1, 9, 4};

    std::ranges::sort(v);
    std::cout << "sorted: ";
    for (int x : v) std::cout << x << ' ';
    std::cout << '\n';

    auto even_squares = v
        | std::views::filter([](int x) { return x % 2 == 0; })
        | std::views::transform([](int x) { return x * x; });

    std::cout << "even squares: ";
    for (int x : even_squares) std::cout << x << ' ';
    std::cout << '\n';
}
Output
sorted: 1 2 4 5 8 9
even squares: 4 16 64

Views do no work until you loop over them, and they do not copy the data.

Common mistakes#

Practice#

Practice exercise

Given std::vector<std::string> words = {"kiwi", "apple", "fig", "banana", "date", "cherry"};, use algorithms to: sort the words by length (shortest first, alphabetical for ties), count the words longer than 4 letters, and find the first word starting with 'b'.

Show solution
C++
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> words = {"kiwi", "apple", "fig", "banana", "date", "cherry"};

    std::sort(words.begin(), words.end(), [](const std::string& a, const std::string& b) {
        if (a.size() != b.size()) return a.size() < b.size();
        return a < b;
    });
    for (const auto& w : words) std::cout << w << ' ';
    std::cout << '\n';

    auto long_words = std::count_if(words.begin(), words.end(),
                                    [](const std::string& w) { return w.size() > 4; });
    std::cout << long_words << " words longer than 4 letters\n";

    auto it = std::find_if(words.begin(), words.end(),
                           [](const std::string& w) { return !w.empty() && w[0] == 'b'; });
    if (it != words.end()) std::cout << "first b-word: " << *it << '\n';
}
Output
fig date kiwi apple banana cherry
3 words longer than 4 letters
first b-word: banana

Key takeaway#

Finished this lesson?