C++ Standard Library Algorithms: sort, find, transform
MSVC STL algorithms in <algorithm> and <numeric>: sorting, searching, transforming, numeric reduction, lambdas, and the C++20 Ranges library with examples.
Use this file to discover all available pages before exploring further.
Algorithms are a cornerstone of the C++ Standard Library. Unlike container member functions, standard algorithms in <algorithm> and <numeric> operate on iterator ranges rather than container objects directly. This design means the same std::sort can sort a vector, an array, a deque, or any other contiguous or random-access sequence — even a raw pointer range. Algorithms never access the container; they see only the elements through iterators, which makes them generic, composable, and independently testable.
The algorithm range convention is [first, last) — a half-open interval that includes the element at first but excludes the element at last. This is the iterator returned by container.end(). Passing an invalid or reversed range is undefined behavior.
stable_sort is identical to sort except it preserves the relative order of equivalent elements. This matters when elements carry extra data beyond their sort key.
When you only need the top-k elements, these algorithms are far more efficient than a full sort:
#include <algorithm>#include <vector>#include <iostream>int main(){ std::vector<int> v = {7, 1, 9, 3, 5, 2, 8, 4, 6}; // partial_sort: first 3 elements are the 3 smallest, fully sorted std::partial_sort(v.begin(), v.begin() + 3, v.end()); std::cout << "3 smallest: " << v[0] << ' ' << v[1] << ' ' << v[2] << "\n"; // 1 2 3 // nth_element: v[4] is the element that would be at index 4 if sorted // Elements before it are <= v[4]; elements after are >= v[4] std::nth_element(v.begin(), v.begin() + 4, v.end()); std::cout << "median-ish: " << v[4] << "\n";}
#include <algorithm>#include <vector>#include <iostream>int main(){ std::vector<int> v = {10, 20, 30, 40, 50}; // find: returns iterator to first match, or end() if not found auto it = std::find(v.begin(), v.end(), 30); if (it != v.end()) std::cout << "Found 30 at index " << std::distance(v.begin(), it) << "\n"; // 2 // find_if: search with a predicate auto it2 = std::find_if(v.begin(), v.end(), [](int x) { return x > 25; }); if (it2 != v.end()) std::cout << "First > 25: " << *it2 << "\n"; // 30 // find_if_not: first element that does NOT satisfy the predicate auto it3 = std::find_if_not(v.begin(), v.end(), [](int x) { return x < 35; }); std::cout << "First >= 35: " << *it3 << "\n"; // 40}
std::remove does not actually erase elements; it shifts unwanted elements to the back and returns an iterator to the new logical end. Pair it with container.erase() to truly remove elements.
#include <algorithm>#include <vector>#include <iostream>int main(){ std::vector<int> v = {1, 2, 3, 2, 4, 2, 5}; // Erase-remove idiom v.erase(std::remove(v.begin(), v.end(), 2), v.end()); for (int x : v) std::cout << x << ' '; // 1 3 4 5 std::cout << "\n"; // C++20: std::erase (free function) does both steps // std::erase(v, 2); // equivalent one-liner in C++20}
The Ranges library in C++20 introduces range adaptors and views that compose lazily without allocating intermediate containers. Ranges algorithms live in the std::ranges namespace.
#include <algorithm>#include <ranges>#include <vector>#include <iostream>int main(){ std::vector<int> v = {5, 3, 1, 4, 2}; // std::ranges::sort — takes a range directly, no begin/end needed std::ranges::sort(v); for (int x : v) std::cout << x << ' '; // 1 2 3 4 5 std::cout << "\n"; // Lazy pipeline: filter evens, double them, take first 3 auto result = v | std::views::filter([](int x) { return x % 2 == 0; }) | std::views::transform([](int x) { return x * 2; }) | std::views::take(2); for (int x : result) std::cout << x << ' '; // 4 8 std::cout << "\n"; // ranges::find with a projection (sort/search by field without a custom comparator) struct Point { int x, y; }; std::vector<Point> pts = {{1, 5}, {2, 3}, {3, 8}}; auto it = std::ranges::find(pts, 3, &Point::y); if (it != pts.end()) std::cout << "Found point with y=3: (" << it->x << ',' << it->y << ")\n";}
Compile with /std:c++20 (or /std:c++latest) to enable <ranges>. Views are lazy — they compute values only when iterated. This makes pipelines like filter | transform | take highly efficient even on large datasets.