Algorithms
STL Algorithms
Section titled “STL Algorithms”The STL provides a rich set of algorithms that work with containers. This chapter covers the most commonly used algorithms.
Algorithm Categories
Section titled “Algorithm Categories”┌─────────────────────────────────────────────────────────────┐│ STL Algorithm Categories │├─────────────────────────────────────────────────────────────┤│ ││ Non-modifying → for_each, find, count, equal ││ Modifying → copy, transform, replace, remove ││ Sorting → sort, stable_sort, partial_sort ││ Binary Search → lower_bound, upper_bound, equal_range││ Set Operations → set_union, set_intersection ││ Heap Operations → make_heap, push_heap, pop_heap ││ Numeric → accumulate, inner_product ││ │└─────────────────────────────────────────────────────────────┘Non-Modifying Algorithms
Section titled “Non-Modifying Algorithms”for_each
Section titled “for_each”Apply function to each element:
#include <algorithm>#include <vector>#include <iostream>
int main() { std::vector<int> vec = {1, 2, 3, 4, 5};
std::for_each(vec.begin(), vec.end(), [](int n) { std::cout << n << " "; }); // Output: 1 2 3 4 5}find / find_if
Section titled “find / find_if”Find first element matching condition:
std::vector<int> vec = {10, 20, 30, 40, 50};
// Find valueauto it = std::find(vec.begin(), vec.end(), 30);if (it != vec.end()) { std::cout << "Found at position: " << (it - vec.begin());}
// Find with conditionauto it2 = std::find_if(vec.begin(), vec.end(), [](int n) { return n > 25; });count / count_if
Section titled “count / count_if”Count elements:
std::vector<int> vec = {1, 2, 3, 2, 4, 2, 5};
int twos = std::count(vec.begin(), vec.end(), 2); // 3int evens = std::count_if(vec.begin(), vec.end(), [](int n) { return n % 2 == 0; }); // 4Modifying Algorithms
Section titled “Modifying Algorithms”Copy elements to another range:
std::vector<int> src = {1, 2, 3, 4, 5};std::vector<int> dest(5);
std::copy(src.begin(), src.end(), dest.begin());
// Copy to output streamstd::copy(src.begin(), src.end(), std::ostream_iterator<int>(std::cout, " "));transform
Section titled “transform”Apply transformation:
std::vector<int> input = {1, 2, 3, 4, 5};std::vector<int> output(input.size());
// Double each elementstd::transform(input.begin(), input.end(), output.begin(), [](int n) { return n * 2; });// output: {2, 4, 6, 8, 10}remove / remove_if
Section titled “remove / remove_if”Remove elements (returns new end):
std::vector<int> vec = {1, 2, 3, 4, 5, 6};
// Remove value 3auto newEnd = std::remove(vec.begin(), vec.end(), 3);vec.erase(newEnd, vec.end()); // {1, 2, 4, 5, 6}
// Remove even numbersauto newEnd2 = std::remove_if(vec.begin(), vec.end(), [](int n) { return n % 2 == 0; });vec.erase(newEnd2, vec.end()); // {1, 3, 5}Sorting Algorithms
Section titled “Sorting Algorithms”O(n log n) sorting:
std::vector<int> vec = {5, 2, 8, 1, 9, 3};
std::sort(vec.begin(), vec.end()); // {1, 2, 3, 5, 8, 9}
// Custom comparatorstd::sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; }); // Descending
// Sort in placestd::stable_sort(vec.begin(), vec.end()); // Maintains equal element orderpartial_sort
Section titled “partial_sort”Sort first N elements:
std::vector<int> vec = {9, 5, 2, 7, 1, 8, 3};
std::partial_sort(vec.begin(), vec.begin() + 3, vec.end());// First 3 are smallest: {1, 2, 3}nth_element
Section titled “nth_element”Partition around nth element:
std::vector<int> vec = {5, 2, 8, 1, 9, 3};
std::nth_element(vec.begin(), vec.begin() + 3, vec.end());// Elements before position 3 are smaller, after are largerBinary Search (on sorted ranges)
Section titled “Binary Search (on sorted ranges)”std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// Binary searchbool found = std::binary_search(vec.begin(), vec.end(), 5); // true
// Lower bound (first not less than value)auto lb = std::lower_bound(vec.begin(), vec.end(), 5);// Points to 5
// Upper bound (first greater than value)auto ub = std::upper_bound(vec.begin(), vec.end(), 5);// Points to 6
// Equal range (both bounds)auto [first, last] = std::equal_range(vec.begin(), vec.end(), 5);Heap Operations
Section titled “Heap Operations”std::vector<int> vec = {3, 1, 4, 1, 5, 9, 2, 6};
// Make heapstd::make_heap(vec.begin(), vec.end());// Now: largest element at front
// Add elementvec.push_back(10);std::push_heap(vec.begin(), vec.end());
// Remove largeststd::pop_heap(vec.begin(), vec.end());vec.pop_back(); // Remove 10Numeric Algorithms
Section titled “Numeric Algorithms”accumulate
Section titled “accumulate”Sum or fold elements:
#include <numeric>#include <vector>
std::vector<int> vec = {1, 2, 3, 4, 5};
int sum = std::accumulate(vec.begin(), vec.end(), 0); // 15
// With custom operationint product = std::accumulate(vec.begin(), vec.end(), 1, [](int a, int b) { return a * b; }); // 120inner_product
Section titled “inner_product”Dot product of two vectors:
std::vector<int> a = {1, 2, 3};std::vector<int> b = {4, 5, 6};
int dot = std::inner_product(a.begin(), a.end(), b.begin(), 0);// 1*4 + 2*5 + 3*6 = 32Complete Example: Processing Data
Section titled “Complete Example: Processing Data”#include <iostream>#include <vector>#include <algorithm>#include <numeric>#include <string>
int main() { std::vector<int> numbers = {5, 2, 8, 1, 9, 3, 7, 4, 6};
// Print original std::cout << "Original: "; std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "\n";
// Count even numbers int evens = std::count_if(numbers.begin(), numbers.end(), [](int n) { return n % 2 == 0; }); std::cout << "Even numbers: " << evens << "\n";
// Transform: square each number std::vector<int> squared(numbers.size()); std::transform(numbers.begin(), numbers.end(), squared.begin(), [](int n) { return n * n; });
std::cout << "Squared: "; std::copy(squared.begin(), squared.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "\n";
// Sort std::sort(numbers.begin(), numbers.end()); std::cout << "Sorted: "; std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "\n";
// Find auto it = std::find(numbers.begin(), numbers.end(), 5); if (it != numbers.end()) { std::cout << "Found 5 at position: " << (it - numbers.begin()) << "\n"; }
// Accumulate int sum = std::accumulate(numbers.begin(), numbers.end(), 0); std::cout << "Sum: " << sum << "\n";
// Min/Max auto minIt = std::min_element(numbers.begin(), numbers.end()); auto maxIt = std::max_element(numbers.begin(), numbers.end()); std::cout << "Min: " << *minIt << ", Max: " << *maxIt << "\n";
// Reverse std::reverse(numbers.begin(), numbers.end()); std::cout << "Reversed: "; std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "\n";
return 0;}Using Lambdas with Algorithms
Section titled “Using Lambdas with Algorithms”Lambdas are commonly used with STL algorithms:
std::vector<int> vec = {1, 2, 3, 4, 5};
// Filter and collectstd::vector<int> result;std::copy_if(vec.begin(), vec.end(), std::back_inserter(result), [](int n) { return n > 3; });
// Sort by custom criteriastd::vector<std::string> words = {"apple", "banana", "cherry"};std::sort(words.begin(), words.end(), [](const std::string& a, const std::string& b) { return a.length() < b.length(); });Key Takeaways
Section titled “Key Takeaways”- STL algorithms work on ranges defined by iterators
- Non-modifying algorithms don’t change container contents
- Modifying algorithms can change or remove elements
- Sorting algorithms have O(n log n) complexity
- Use lambdas for custom comparison and transformation logic
- Algorithms work with any container supporting the required iterators
Next Steps
Section titled “Next Steps”Let’s learn about iterators.
Next Chapter: 18_iterators.md - Iterators and Ranges