STL Algorithms and Iterators in C++
- 1. Key Concepts & Code Explanations
- 1.1 Iterator Categories
- 1.2 Non-Modifying Algorithms
- 1.3 Modifying Algorithms
- 1.4 Sorting and Searching
- 1.5 Custom Comparators and Predicates
- 2. Hard Multiple-Choice Questions (10)
- Questions 1-5
- Questions 6-10
- Answers & Explanations
- 3. Medium Design Questions (5)
- Question 1: Custom Filter with `std::copy_if`
- Question 2: Custom Comparator for Sorting Strings
- Question 3: Implement `std::accumulate` with a Lambda
- Question 4: Remove Duplicates Using `std::unique`
- Question 5: Custom Iterator for a Range
- Summary
1. Key Concepts & Code Explanations
1.1 Iterator Categories
What: Iterators are abstractions for accessing elements in containers.
Categories:
- Input: Read-only, forward traversal (e.g.,
istream_iterator
). - Output: Write-only, forward traversal (e.g.,
ostream_iterator
). - Forward: Read/write, single-pass (e.g.,
forward_list
). - Bidirectional: Read/write, bidirectional (e.g.,
list
). - Random Access: Direct access (e.g.,
vector
,array
).
Example: Random-access iterator with std::vector
:
#include <vector>
#include <algorithm>int main() {std::vector<int> vec = {5, 3, 1, 4, 2};std::sort(vec.begin(), vec.end()); // Requires random-access iteratorsfor (auto it = vec.begin(); it != vec.end(); ++it)std::cout << *it << " "; // Output: 1 2 3 4 5
}
1.2 Non-Modifying Algorithms
What: Algorithms that inspect but do not modify elements.
Examples: std::find
, std::count
, std::for_each
.
Example: Find an element in a vector
:
#include <algorithm>int main() {std::vector<int> vec = {10, 20, 30, 40};auto it = std::find(vec.begin(), vec.end(), 30);if (it != vec.end())std::cout << "Found at position " << (it - vec.begin()); // Output: 2
}
1.3 Modifying Algorithms
What: Algorithms that modify elements (e.g., std::copy
, std::transform
).
Example: Transform elements with a lambda:
#include <vector>
#include <algorithm>int main() {std::vector<int> src = {1, 2, 3};std::vector<int> dst(src.size());std::transform(src.begin(), src.end(), dst.begin(), [](int x) { return x * 2; });for (int x : dst)std::cout << x << " "; // Output: 2 4 6
}
1.4 Sorting and Searching
What: Algorithms like std::sort
, std::binary_search
.
Example: Sort and search a vector
:
#include <algorithm>int main() {std::vector<int> vec = {5, 3, 1, 4, 2};std::sort(vec.begin(), vec.end()); // Sorts to {1, 2, 3, 4, 5}bool found = std::binary_search(vec.begin(), vec.end(), 3); // truestd::cout << found; // Output: 1
}
1.5 Custom Comparators and Predicates
What: Use lambdas or functors to customize algorithm behavior.
Example: Sort in descending order:
#include <algorithm>
#include <vector>int main() {std::vector<int> vec = {5, 3, 1, 4, 2};std::sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; });for (int x : vec)std::cout << x << " "; // Output: 5 4 3 2 1
}
2. Hard Multiple-Choice Questions (10)
Questions 1-5
Q1: Which iterator category is required for std::sort
?
A) Input
B) Forward
C) Random Access
D) Output
Q2: What is the output of std::count
for vec = {2, 4, 6, 4}
with value = 4
?
A) 0
B) 1
C) 2
D) 3
Q3: Which algorithm copies elements from one container to another?
A) std::move
B) std::copy
C) std::transform
D) std::fill
Q4: What is the time complexity of std::sort
?
A) O(n)
B) O(n log n)
C) O(n²)
D) O(1)
Q5: What does std::remove
actually do?
A) Deletes elements from the container
B) Moves elements to the end and returns a new logical end
C) Replaces elements with a default value
D) Sorts the container
Questions 6-10
Q6: Which algorithm requires a sorted range?
A) std::find
B) std::binary_search
C) std::count
D) std::for_each
Q7: What is the output of the following code?
std::vector<int> vec = {1, 2, 3};
std::fill(vec.begin(), vec.end(), 0);
std::cout << vec[1];
A) 0
B) 1
C) 2
D) 3
Q8: Which iterator type can move backward?
A) Input
B) Forward
C) Bidirectional
D) Output
Q9: What does std::transform
’s lambda return type determine?
A) The container type
B) The type of elements in the destination
C) The iterator category
D) The algorithm’s complexity
Q10: What is the result of std::max_element
on vec = {3, 1, 4}
?
A) 1
B) 3
C) 4
D) Returns an iterator pointing to 4
Answers & Explanations
- C (Random access required for efficient sorting).
- C (Two occurrences of
4
). - B (
std::copy
copies elements). - B (Average case O(n log n)).
- B (Elements are moved, but the container size remains unchanged).
- B (
binary_search
requires a sorted range). - A (
fill
sets all elements to 0). - C (Bidirectional iterators allow backward traversal).
- B (The lambda’s return type must match the destination element type).
- D (Returns an iterator, not the value).
3. Medium Design Questions (5)
Question 1: Custom Filter with std::copy_if
Task: Copy even numbers from one vector
to another.
#include <vector>
#include <algorithm>int main() {std::vector<int> src = {1, 2, 3, 4, 5};std::vector<int> dst;std::copy_if(src.begin(), src.end(), std::back_inserter(dst), [](int x) { return x % 2 == 0; });for (int x : dst)std::cout << x << " "; // Output: 2 4
}
Question 2: Custom Comparator for Sorting Strings
Task: Sort strings by length.
#include <vector>
#include <algorithm>
#include <string>int main() {std::vector<std::string> vec = {"apple", "banana", "cherry"};std::sort(vec.begin(), vec.end(), [](const auto& a, const auto& b) { return a.size() < b.size(); });for (const auto& s : vec)std::cout << s << " "; // Output: apple cherry banana
}
Question 3: Implement std::accumulate
with a Lambda
Task: Compute the product of elements.
#include <vector>
#include <numeric>int main() {std::vector<int> vec = {1, 2, 3, 4};int product = std::accumulate(vec.begin(), vec.end(), 1, [](int a, int b) { return a * b; });std::cout << product; // Output: 24
}
Question 4: Remove Duplicates Using std::unique
Task: Remove consecutive duplicates.
#include <vector>
#include <algorithm>int main() {std::vector<int> vec = {1, 2, 2, 3, 3, 3, 4};auto last = std::unique(vec.begin(), vec.end());vec.erase(last, vec.end());for (int x : vec)std::cout << x << " "; // Output: 1 2 3 4
}
Question 5: Custom Iterator for a Range
Task: Create an iterator that traverses a vector
in reverse.
#include <vector>
#include <iterator>int main() {std::vector<int> vec = {1, 2, 3, 4};for (auto it = vec.rbegin(); it != vec.rend(); ++it)std::cout << *it << " "; // Output: 4 3 2 1
}
Summary
This guide covers STL algorithms (non-modifying, modifying, sorting), iterators (categories and usage), and custom operations (comparators, predicates). Test cases validate correctness for common tasks like filtering, transforming, and sorting. The exercises reinforce practical applications of algorithms and iterators.