Partitioning Without Random Access Iterators

Is it possible to use the partition() algorithm with containers that do not support random access iterators?

Yes, you can use the partition() algorithm with containers that do not support random access iterators, such as linked lists.

The C++ standard library's partitioning algorithms are designed to work with any container that meets the requirements of bidirectional iterators.

Requirements for Partitioning

The partition() algorithm requires bidirectional iterators because it needs to traverse the container from both ends to swap elements. Containers like std::list, which provide bidirectional iterators, are compatible with partition().

Here's an example using std::list:

#include <algorithm>
#include <iostream>
#include <list>

int main() {
  std::list<int> A = {1, -6, 7, 2, 5, 4};

  auto isEven = [](int x) { return x % 2 == 0; };

  std::partition(A.begin(), A.end(), isEven);

  std::cout << "After partitioning: ";
  for (int x : A) {
    std::cout << x << ", ";
  }
}
After partitioning: -6, 2, 4, 1, 7, 5,

In this example, std::partition works with std::list because std::list provides bidirectional iterators. The elements are rearranged such that even numbers come before odd numbers.

Why Random Access Iterators Aren't Required

Random access iterators allow direct access to any element in the container using indexing, which is not necessary for partitioning. The partition() algorithm only requires bidirectional iterators to move forward and backward through the container, making swaps where necessary.

Practical Use

Here's a practical example with std::list showing a more complex partitioning scenario:

#include <algorithm>
#include <iostream>
#include <list>

int main() {
  std::list<int> A = {3, 6, 1, 5, 8, 2, 7};

  auto isLessThanFive = [](int x) { return x < 5; };

  auto partition_point = std::partition(
    A.begin(), A.end(), isLessThanFive);

  std::cout << "Elements less than 5: ";
  for (auto it = A.begin();
    it != partition_point; ++it) {
    std::cout << *it << ", ";
  }
  std::cout << "\nElements 5 or greater: ";
  for (auto it = partition_point;
    it != A.end(); ++it) {
    std::cout << *it << ", ";
  }
}
Elements less than 5: 3, 1, 2,
Elements 5 or greater: 6, 5, 8, 7,

Conclusion

Using partition() with containers that support bidirectional iterators, like std::list, is straightforward.

Ensure your container provides at least bidirectional iterators to take advantage of the partitioning algorithms in the C++ standard library.

Partition Algorithms

An introduction to partitions, and the C++ standard library algorithms that create them

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Partition vs Stable Partition Performance
How does the partition() algorithm differ from the stable_partition() algorithm in terms of performance?
Partitioning Custom Data Types
Can the partition() function be used with custom data types, and if so, how?
Determining Partition Size
How can I determine the size of each partition after using the partition() function?
When to Use partition_copy()
What are the use cases for partition_copy() over partition() or stable_partition()?
Understanding partition_point()
How does the partition_point() algorithm determine the boundary between partitions?
Safe Iterator Handling in partition_point()
How can I handle the iterator returned by partition_point() to avoid dereferencing issues?
Alternatives to partition()
Are there any alternatives to using std::partition() or std::ranges::partition() that offer better performance or additional features?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant