Concepts / Common STL Algorithms and Their Inputs

Common STL Algorithms and Their Inputs

An STL algorithm operates on one or more sequences.

  • Programming

Why an Algorithm Needs to Know Its Input

The STL provides algorithms that do useful work on collections of data. Before you can use one well, you need to know what it expects as input. The central idea is simple: an STL algorithm operates on one or more sequences. Rather than being tied to one particular container, the algorithm works on a sequence of elements that it is given.

As you read this article, keep one question in mind: when an algorithm receives a sequence, exactly which elements does it work on? The answer depends on how the sequence is specified, and the specification is what this article is about.

Tracing a Sequence Through an Algorithm

Think of a sequence as a row of positions, each holding one element. An algorithm reads the elements it is given and does its work on them. To follow what happens, imagine a row of five values: 10, 20, 30, 40, 50, numbered by position from 0 to 4. Nothing about the algorithm has been decided yet. The only question is which part of this row it has been handed.

The source describes the relationship between an algorithm and its inputs in general terms: the algorithm does its work on the sequences it is given, and each of those sequences is what it reads from and acts on. The rest of this article shows how a single sequence is marked out so that the algorithm knows where its work begins and ends.

Marking a Sequence With Two Iterators

Definition

An input sequence is half-open and defined by a pair of iterators. The first iterator marks where the sequence begins, and the second marks where it ends. The pair of iterators together specifies the range that the algorithm works on, so both iterators must be considered together rather than one at a time.

Conventionally these two iterators are named first and last. Written as a range, the input is $[\mathrm{first}, \mathrm{last})$. The square bracket on the left means the first iterator's position is included. The round bracket on the right means the last iterator's position is not included. This asymmetry is the whole meaning of half-open.

10index 0, before the range20first30included40included50last, not included
Given the row of five values and the iterator pair first and last, which exact positions does the algorithm process, and why is the element at last excluded?

In the diagram, first points at the element 20 and last points at the element 50. The algorithm processes 20, 30 and 40. The element at last, which is 50, is not processed. The end iterator marks the boundary of the range, not its final element.

The Empty Range

Because the first iterator is included and the last iterator is not, what happens when both iterators point to the same position? The pair describes a range that starts and stops at the same spot. Nothing lies between them that is both at or after first and before last, so the range contains zero elements.

10outside the range20first and last30outside the range
When both iterators point to the same position, which positions does the range include, and why does it contain zero elements?

In this diagram both iterators sit on the element 20. The range $[\mathrm{first}, \mathrm{last})$ would need to include position 1 and stop before position 1, which cannot be done. The algorithm therefore receives no elements to work on. Being able to recognize this case matters, because it means the half-open convention handles the empty sequence without any special rule.

One Sequence or Several

Algorithms differ in how many sequences they take. Some work on a single sequence, and others work on more than one. The source states the general rule: an STL algorithm operates on one or more sequences. Each sequence an algorithm receives is described the same way, by its own pair of iterators, so the same reading rules apply to every input.

Sequence Aone iterator pairSequence Aits own iterator pairSequence Bits own iterator pair
How many input ranges does an algorithm take when it works on one sequence, and how does that change when it works on several?

The diagram shows two sequences, but the same idea applies to a single sequence. What matters is the relationship: the algorithm does its work on the sequences it is given, and each one is read through its own pair of iterators. Adding a second sequence does not change how a single range is read; it adds one more range to be read in the same way.

Mistakes Beginners Make With Ranges

  • Common mistake

    Treating last as the final element of the sequence

    What it looks like

    With values 10, 20, 30, 40, 50 and last at position 4, assuming the element 50 is processed.

    Why it fails

    The range is half-open, so the position last is not included. Only positions from first up to but not including last are processed.

    Do this instead

    Read the range as [first, last) and count the included elements as last minus first.

  • Common mistake

    Reading the two iterators separately

    What it looks like

    Looking at first alone and deciding the algorithm starts at the right place, without checking where last stops it.

    Why it fails

    The pair of iterators together specifies the range. Neither iterator tells the full story by itself.

    Do this instead

    Always read first and last as a pair before deciding which elements the algorithm processes.

  • Common mistake

    Expecting an empty range to be an error

    What it looks like

    Passing first and last at the same position and expecting the algorithm to fail.

    Why it fails

    When first equals last, the range contains zero elements. That is a valid, well-defined input.

    Do this instead

    Recognize equal iterators as an empty range and understand that the algorithm simply has nothing to process.

  • Common mistake

    Assuming an algorithm can only ever be given one sequence

Checking Your Reading of a Range

EASY

A sequence holds the values 5, 8, 13, 21, 34, 55 at positions 0 through 5. An algorithm is given first at position 2 and last at position 5. Which values are processed, and how many are there?

Hints
  • Start at the position first points to, then move forward one position at a time.
  • Stop as soon as you reach last, and do not process the element sitting at last.
  • The number of elements is last minus first.

What do you think happens?

If first and last both point to position 3 in the same sequence, how many elements does the algorithm process?

Reveal answer
Answer:

Zero elements. The range is empty because first and last mark the same position, and the end position is excluded.

The half-open convention means the range runs from first up to but not including last. When they coincide, there is no position in between.

Key Takeaways

  • An STL algorithm operates on one or more sequences, and the sequences it receives are the inputs it reads from and acts on.
  • An input sequence is half-open and defined by a pair of iterators, first and last, which must be read together.
  • A half-open range $[\mathrm{first}, \mathrm{last})$ includes the element at first and excludes the element at last.
  • When first and last point to the same position, the range is empty and contains zero elements.

Related concepts

More concepts starting with C