Stl Algorithms

By the end of this lesson you'll replace hand-written loops with the C++ Standard Library's algorithm and numeric tools — sorting with your own rules, searching, summing, transforming, and safely deleting elements — using one line where you used to write fifteen.

Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.

Part of the free C++ course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Think of STL algorithms as power tools . You could cut every plank with a hand saw (your own for loop), but a builder reaches for the right power tool: a circular saw to cut ( sort ), a stud finder to locate ( find ), a tape measure to total up ( accumulate ). Each tool clamps onto a stretch of work — that's the iterator range , from begin() to end() . You supply the rule (a lambda : "cut here", "keep this one") and the tool does the repetitive work, faster and with fewer mistakes than doing it by hand.

1. Sort, Find & Count

std::sort rearranges a range in place — ascending by default. To sort by your rule, pass a third argument: a comparator . A comparator is a lambda that takes two elements and returns a bool answering one question — "should a come before b ?" Return a b and you've flipped it to descending. find hunts for an exact value and hands back an iterator (compare it to end() to check for a miss), while count and count_if tally matches. Read this worked example, run it, then you'll write your own.

Your turn. The program below is almost complete — fill in the two blanks marked ___ using the hints, then run it and check it against the expected output.

2. Accumulate, Transform & for_each

std::accumulate (from numeric , not algorithm ) folds a whole range into a single value — its third argument is both the starting total and the type of the result. std::transform applies a function to every element and writes the results into another range. std::for_each runs an action on each element without producing a new range. And min_element / max_element return an iterator to the smallest or largest value — remember to dereference it with * to read the value out.

Now you try. Total a list of workout minutes, then convert each one to hours. Fill in the two blanks — watch the type on the accumulate seed and the division:

3. Deleting Elements: the Erase-Remove Idiom

This is the one that surprises everybody. std::remove and std::remove_if do not actually delete anything . An algorithm only sees a pair of iterators — it has no power to resize the container. So remove just shuffles the elements you're keeping to the front and returns an iterator to the new logical end ; the leftover slots are still there. To truly shrink the container you pass that iterator to the container's own erase() method. Doing both together is the famous erase-remove idiom .

No blanks this time — just a brief and an outline to keep you on track. Combine sort , min_element / max_element , accumulate , and count_if into one small report. Build it, run it, and check your output against the example in the comments.

Practice quiz

Which header is std::sort, std::find, and std::count_if declared in?

  • <numeric>
  • <vector>
  • <algorithm>
  • <functional>

Answer: <algorithm>. sort, find, count_if, transform, for_each, remove_if and min/max_element all live in <algorithm>.

Which header does std::accumulate live in?

  • <numeric>
  • <algorithm>
  • <vector>
  • <cmath>

Answer: <numeric>. accumulate lives in <numeric>, not <algorithm> — a common include mistake.

What should a comparator lambda passed to std::sort return?

  • The larger of the two elements
  • An int: -1, 0, or 1
  • The sorted range
  • A bool answering 'should a come before b?'

Answer: A bool answering 'should a come before b?'. A comparator returns a bool — true when a should sort before b. Use a < b for ascending, a > b for descending.

To sort a vector in DESCENDING order, the comparator should return:

  • a < b
  • a > b
  • a <= b
  • a == b

Answer: a > b. Returning a > b means bigger elements come first, giving descending order.

What does std::find return?

  • An iterator to the element, or end() if not found
  • The matching value, or 0 if not found
  • The index of the element
  • A bool

Answer: An iterator to the element, or end() if not found. find returns an iterator; compare it to end() to detect a miss.

What is the result of accumulate(v.begin(), v.end(), 0) for v = {1299, 2499, 599, 3999, 899}?

  • 5
  • 3999
  • 9295
  • 0

Answer: 9295. accumulate folds the range starting from the seed 0: 1299+2499+599+3999+899 = 9295.

Why does the seed type in accumulate matter, e.g. 0 vs 0.0?

  • It controls the iteration order
  • It fixes the result type — 0 sums as int and truncates decimals, 0.0 sums as double
  • 0.0 is invalid for accumulate
  • It changes which header is needed

Answer: It fixes the result type — 0 sums as int and truncates decimals, 0.0 sums as double. The seed sets the accumulation type; seeding with int 0 truncates decimals, while 0.0 keeps them.

What does std::transform do?

  • Sorts a range in place
  • Removes elements that match a predicate
  • Counts matching elements
  • Applies a function to every element and writes results into another range

Answer: Applies a function to every element and writes results into another range. transform maps each input element through a function into an output range.

What do min_element and max_element return?

  • The smallest/largest value directly
  • An iterator to the smallest/largest element — dereference with * to read the value
  • An index
  • A sorted copy of the range

Answer: An iterator to the smallest/largest element — dereference with * to read the value. They return iterators; you write *max_element(v.begin(), v.end()) to get the value.

Why must remove_if be paired with the container's erase() (the erase-remove idiom)?

  • erase is faster than remove_if
  • remove_if deletes the wrong elements without erase
  • remove_if only shifts kept elements forward and returns the new logical end; it can't resize the container
  • erase sorts the range first

Answer: remove_if only shifts kept elements forward and returns the new logical end; it can't resize the container. Algorithms see only iterators, so remove_if can't shrink the container — erase() does the actual shrinking.