STL Algorithms Quick Reference
Complete STL algorithms cheat sheet — sorting, searching, transforming, partitioning, set operations, and numeric algorithms with usage examples.
Sorting
cpp
#include <algorithm>
// Sort in-place — O(n log n)
std::sort(v.begin(), v.end()); // ascending
std::sort(v.begin(), v.end(), std::greater<int>{}); // descending
std::sort(v.begin(), v.end(), [](const T& a, const T& b) { return a.key < b.key; });
// Ranges versions (C++20)
std::ranges::sort(v);
std::ranges::sort(v, {}, &Person::age); // sort by member (projection)
// Stable sort — preserves relative order of equal elements
std::stable_sort(v.begin(), v.end());
// Partial sort — first n elements sorted, rest unordered
std::partial_sort(v.begin(), v.begin() + n, v.end());
// nth element — element that would be at position n if sorted
std::nth_element(v.begin(), v.begin() + n, v.end());
// v[n] is correct; v[0..n-1] ≤ v[n] ≤ v[n+1..end]
// Check if sorted
std::is_sorted(v.begin(), v.end());
std::ranges::is_sorted(v);Searching
cpp
// Linear search — O(n)
auto it = std::find(v.begin(), v.end(), value);
auto it2 = std::find_if(v.begin(), v.end(), predicate);
auto it3 = std::find_if_not(v.begin(), v.end(), predicate);
// Binary search — O(log n), requires sorted range
bool found = std::binary_search(v.begin(), v.end(), value);
auto it4 = std::lower_bound(v.begin(), v.end(), value); // first ≥ value
auto it5 = std::upper_bound(v.begin(), v.end(), value); // first > value
auto [lo, hi] = std::equal_range(v.begin(), v.end(), value); // range of equals
// Min/max
auto it6 = std::min_element(v.begin(), v.end());
auto it7 = std::max_element(v.begin(), v.end());
auto [min_it, max_it] = std::minmax_element(v.begin(), v.end());
// Ranges
auto it8 = std::ranges::find(v, value);
auto it9 = std::ranges::find_if(v, pred);
auto min = std::ranges::min_element(v);Counting and testing
cpp
// Count
long n = std::count(v.begin(), v.end(), value);
long n2 = std::count_if(v.begin(), v.end(), predicate);
// Test all/any/none
bool all = std::all_of(v.begin(), v.end(), predicate);
bool any = std::any_of(v.begin(), v.end(), predicate);
bool none = std::none_of(v.begin(), v.end(), predicate);
// Ranges
auto n3 = std::ranges::count(v, value);
bool all2 = std::ranges::all_of(v, predicate);Transforming
cpp
#include <algorithm>
// transform — apply function to each element
std::transform(in.begin(), in.end(), out.begin(), func);
std::transform(a.begin(), a.end(), b.begin(), out.begin(), binary_func);
// for_each — apply function for side effects
std::for_each(v.begin(), v.end(), [](int& x) { x *= 2; });
// replace
std::replace(v.begin(), v.end(), old_val, new_val);
std::replace_if(v.begin(), v.end(), predicate, new_val);
std::replace_copy(in.begin(), in.end(), out.begin(), old_val, new_val);
// fill and generate
std::fill(v.begin(), v.end(), value);
std::fill_n(v.begin(), n, value);
std::generate(v.begin(), v.end(), generator_fn); // calls fn() for each
std::generate_n(v.begin(), n, generator_fn);
// copy
std::copy(in.begin(), in.end(), out.begin());
std::copy_if(in.begin(), in.end(), out.begin(), predicate);
std::copy_n(in.begin(), n, out.begin());
std::copy_backward(in.begin(), in.end(), out.end()); // copy in reverse order
// move
std::move(in.begin(), in.end(), out.begin());Removing elements
cpp
// remove (erase-remove idiom) — moves kept elements to front
auto it = std::remove(v.begin(), v.end(), value); // doesn't resize!
v.erase(it, v.end()); // actual erase
// remove_if
auto it2 = std::remove_if(v.begin(), v.end(), predicate);
v.erase(it2, v.end());
// C++20 — std::erase / std::erase_if (no idiom needed)
std::erase(v, value);
std::erase_if(v, predicate); // works for vector, map, set, etc.
// unique — remove consecutive duplicates (sort first for all-unique)
std::sort(v.begin(), v.end());
auto it3 = std::unique(v.begin(), v.end());
v.erase(it3, v.end());Partitioning
cpp
// partition — elements satisfying predicate come first
auto it = std::partition(v.begin(), v.end(), predicate);
// [begin, it) satisfy predicate; [it, end) do not
// stable_partition — preserves relative order
std::stable_partition(v.begin(), v.end(), predicate);
// is_partitioned
bool ok = std::is_partitioned(v.begin(), v.end(), predicate);
// partition_copy — copy to two output ranges
std::partition_copy(in.begin(), in.end(),
yes_out.begin(), no_out.begin(), predicate);Set operations (on sorted ranges)
cpp
// All require sorted input ranges
// merge — merge two sorted ranges
std::merge(a.begin(), a.end(), b.begin(), b.end(), out.begin());
std::inplace_merge(v.begin(), v.begin() + n, v.end()); // merge within vector
// set operations
std::set_union(a.begin(), a.end(), b.begin(), b.end(), out.begin());
std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), out.begin());
std::set_difference(a.begin(), a.end(), b.begin(), b.end(), out.begin());
std::set_symmetric_difference(a.begin(), a.end(), b.begin(), b.end(), out.begin());
// Membership
std::includes(big.begin(), big.end(), small.begin(), small.end());Heap operations
cpp
// Build a max-heap
std::make_heap(v.begin(), v.end());
v.front(); // max element
// Push/pop heap (maintains heap property)
v.push_back(new_val);
std::push_heap(v.begin(), v.end());
std::pop_heap(v.begin(), v.end()); // moves max to back
v.pop_back();
// Sort using heap (heap sort)
std::sort_heap(v.begin(), v.end()); // destroys heap propertyNumeric algorithms
cpp
#include <numeric>
// Accumulate (fold)
int sum = std::accumulate(v.begin(), v.end(), 0);
int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>{});
// reduce (C++17) — like accumulate but parallelizable
int sum2 = std::reduce(v.begin(), v.end());
int sum3 = std::reduce(std::execution::par, v.begin(), v.end());
// transform_reduce (C++17) — map then reduce
double dot = std::transform_reduce(a.begin(), a.end(), b.begin(), 0.0);
// a[0]*b[0] + a[1]*b[1] + ...
// inclusive/exclusive scan (prefix sum)
std::vector<int> out(v.size());
std::inclusive_scan(v.begin(), v.end(), out.begin()); // out[i] = sum[0..i]
std::exclusive_scan(v.begin(), v.end(), out.begin(), 0); // out[i] = sum[0..i-1]
// adjacent_difference — difference between consecutive elements
std::adjacent_difference(v.begin(), v.end(), out.begin());
// out[0]=v[0], out[i]=v[i]-v[i-1]
// iota — fill with incrementing values
std::iota(v.begin(), v.end(), 0); // 0, 1, 2, 3, ...
std::iota(v.begin(), v.end(), 10); // 10, 11, 12, 13, ...
// inner_product
int dot2 = std::inner_product(a.begin(), a.end(), b.begin(), 0);
// C++23 fold_left / fold_right
int sum4 = std::ranges::fold_left(v, 0, std::plus{});
int sum5 = std::ranges::fold_right(v, 0, std::plus{});Permutations
cpp
// next/prev permutation (modifies in place, returns false on wrap)
std::sort(v.begin(), v.end());
do {
process(v);
} while (std::next_permutation(v.begin(), v.end()));
// iterates through all permutations
// Shuffle
std::mt19937 rng(std::random_device{}());
std::shuffle(v.begin(), v.end(), rng);
// Rotate
std::rotate(v.begin(), v.begin() + n, v.end()); // v[n] becomes v[0]
// Reverse
std::reverse(v.begin(), v.end());
std::reverse_copy(in.begin(), in.end(), out.begin());Parallel execution policies (C++17)
cpp
#include <execution>
// seq — sequential (default behavior)
std::sort(std::execution::seq, v.begin(), v.end());
// par — parallel (multi-core)
std::sort(std::execution::par, v.begin(), v.end());
// par_unseq — parallel + SIMD vectorized
std::transform(std::execution::par_unseq,
v.begin(), v.end(), v.begin(), [](int x) { return x * 2; });
// Available for: sort, for_each, transform, reduce, find, count, copy, ...