Iterators and Ranges in Algorithms
A sequence is defined by a pair of iterators written as $[\text{begin} : \text{end})$.
The Question Before the Algorithm
When you write an algorithm, you usually want it to work on a group of values rather than on one value at a time. Before you can design that algorithm, you need a precise answer to a simple question: exactly which group of values will the algorithm work on? In this part of the course, the answer is the sequence. A sequence is the unit an algorithm is applied to. Understanding how it relates to the containers that hold data is the first step toward writing algorithms that work across many different kinds of storage.
Keep that question in mind as you read. By the end of this article you should be able to look at two positions, say a starting point and a stopping point, and state exactly which values an algorithm would see.
Following a Range Through Positions
Picture a row of five values stored in positions 0 through 4. Suppose we pick a begin position of 1 and an end position of 4. The sequence those two positions describe starts at the value in position 1 and runs up to, but does not include, the value in position 4. The diagram below marks the values that fall inside that stretch.
Read the diagram from left to right. Position 0 is before the sequence, so A is not part of it. Positions 1, 2 and 3 are covered, so B, C and D form the sequence. Position 4 is the end position, and E is excluded. The sequence therefore contains exactly three values, even though the two boundary positions are 1 and 4.
What do you think happens?
Using the same five values, if the begin position is 1 and the end position is 2, how many values does the sequence contain, and which one is it?
Reveal answer
One value, B
The sequence starts at position 1 and stops before position 2, so it covers only position 1, which holds B.
The Begin and End Pair
A sequence is defined by a pair of iterators written as $[\text{begin} : \text{end})$. The begin iterator marks the first position in the sequence. The end iterator marks the position just past the last one. The sequence includes everything from begin up to, but not including, end.
The square bracket on the left of $[\text{begin} : \text{end})$ means the begin position is included. The round bracket on the right means the end position is excluded. Mathematicians call this a half-open range, because one end is closed and the other is open. The notation is a compact way of saying exactly which positions belong to the sequence, and nothing else is needed to describe it.
Because a sequence is described only by its two boundaries, the definition does not depend on how the values are stored. The source calls this a general and flexible definition. Two positions are all you need to hand to an algorithm.
Container Versus Sequence
The two ideas are easy to blur together, because in practice a container and its contents are usually handled as one thing. Separating them makes clear what each one does. A container is the holder of contents. It is where the data lives. A sequence is a definition of which of those contents an algorithm should consider, given by a pair of iterators.
Notice the direction of the relationship. The sequence is not a second copy of the data. It is a way of naming a stretch of it. The container supplies the values, and the iterator pair tells the algorithm which ones to process. This is why algorithms are most often applied to sequences that are the contents of a container.
| Aspect | Container | Sequence |
|---|---|---|
| Role | Holds the contents | Names a stretch of values an algorithm should consider |
| Where the values live | In the container itself | Still in the container; the sequence is not a second copy |
| What defines it | Its place as the holder of data | A pair of iterators, written $[\text{begin} : \text{end})$ |
| Generality | Tied to a particular storage arrangement | General and flexible; the definition needs only two boundaries |
| Relationship to algorithms | Usually the source of the values | The unit an algorithm is applied to |
The container stores the data, while the sequence describes which part of it an algorithm works on.
The sequence is the more general idea. It does not require any particular container, but in practice it is most often used with one. Because the algorithm receives only the two boundaries, the same algorithm can be pointed at different containers, or at only part of one, simply by changing the pair of positions it is given.
Tracing a Worked Range
Finding the covered positions of a range
A container holds eight values in positions 0 through 7. An algorithm is given the iterator pair with begin at position 2 and end at position 5. Which positions does the sequence cover, and how many values does it contain?
- 1Identify begin
Begin is position 2. The sequence starts there, and position 2 is included.
- 2Identify end
End is position 5. The sequence stops just before it, so position 5 is excluded.
- 3List the covered positions
Positions 2, 3 and 4 are covered. Position 5 is not.
- 4Count the values
Three positions are covered, so the sequence contains three values.
The sequence covers positions 2, 3 and 4, which is three values. Position 5 is the end boundary and is not part of it.
The same procedure works for any pair of positions. Count from begin upward, stop before end, and the covered positions are exactly the ones you collected. The number of values is the distance between the two boundaries, because the end position is never counted.
Empty Ranges When Begin Equals End
What happens when the begin and end positions are the same? Using the definition, the sequence includes everything from begin up to but not including end. If both point to the same position, there is no position that is both at or after begin and before end. The sequence therefore contains no values.
In the diagram, none of the values are highlighted, because the sequence starts and stops at the same boundary. It is still a valid sequence; it simply has length zero. This is a useful case to recognize, because an algorithm given an empty range has nothing to process and should be written to handle that cleanly.
What do you think happens?
If begin is at position 3 and end is also at position 3, how many values does the sequence contain?
Reveal answer
Zero values
The sequence covers positions from 3 up to but not including 3, so no position is covered.
Mistakes When Reading a Range
Common mistake Including the end position in the sequence
What it looks likeBegin is 1 and end is 4, and the reader counts positions 1 through 4 as four values.
Why it failsThe notation $[\text{begin} : \text{end})$ excludes the end position, so position 4 is a boundary, not a member.
Do this insteadCount positions from begin up to end minus one. Here that is positions 1, 2 and 3, which is three values.
Common mistake Treating the sequence as a separate copy of the data
What it looks likeA reader assumes that creating a sequence duplicates the values from the container.
Why it failsThe sequence is only a way of naming a stretch of the container's contents. The data stays where it lives.
Do this insteadThink of the iterator pair as pointing into the container, not as a second store of values.
Common mistake Confusing the container with the sequence
What it looks likeA reader says the algorithm works on the container when it is given a pair of positions.
Why it failsThe container holds the data, but the algorithm is applied to the sequence the iterator pair describes.
Do this insteadName the container as the source of values and the sequence as the part of it that is processed.
Common mistake Forgetting that begin equal to end describes an empty sequence rather than an error
Trace the Range
A container holds six values in positions 0 through 5. An algorithm is given begin at position 1 and end at position 4. List the positions the sequence covers and state how many values it contains. Then say what changes if end is moved to position 6.
Hints
- Start at begin and count upward, stopping before end.
- The end position itself is never covered.
- Moving end to position 6 extends the sequence to include position 5 as well.
Explain in one or two sentences why an algorithm can be applied to only part of a container, and what the iterator pair contributes to that choice.
Hints
- Recall that the sequence is described only by its two boundaries.
- Think about the difference between the container and the sequence named by the iterators.
Summary of Sequences and Ranges
- 1A sequence is defined by a pair of iterators written as $[\text{begin} : \text{end})$, covering everything from begin up to but not including end.
- 2The begin position is included in the sequence and the end position is excluded, so the number of values is the distance between the two boundaries.
- 3A container holds the data, while the sequence is a way of naming a stretch of its contents for an algorithm to process.
- 4Algorithms are most often applied to sequences that are the contents of a container, and an empty range occurs when begin and end are the same position.
At a glance
- A sequence is defined by a pair of iterators written as $[\text{begin} : \text{end})$, covering the values from begin up to but not including end.
- The begin position is included and the end position is excluded, so the sequence's length is the distance between the two boundaries.
- A container holds the data; a sequence is a general, flexible way of naming a stretch of its contents for an algorithm to process.
- Algorithms are usually applied to sequences drawn from a container, and begin equal to end describes an empty sequence.