Reputation: 39
stable_partition(vect.begin(), vect.end(), [](int x) { return x % 2 == 0; });
partition(vect.begin(), vect.end(), [](int x) {
return x % 2 == 0;
});
Above code is to explain difference between two.
Upvotes: 2
Views: 2751
Reputation: 26342
As explained in other answers, std::stable_partition
preserves the relative order of elements in the groups for which the predicate returns true
and false
.
But this comes at a price: std::stable_partition
has higher time/space complexity. If you can allocate additional storage, std::stable_partition
can be implemented in O(n)
time. However, in-place stable partition cannot be implemented in O(n)
time. It can be done in O(n log n)
time. An example of a simple divide-and-conquer algorithm can be found here.
C++ reference for std::stable_partition
reads:
Complexity (
std::stable_partition
)Given
N = last - first
,Exactly
N
applications of the predicate andO(N)
swaps if there is enough extra memory. If memory is insufficient, at mostN log N
swaps.
Also note that std::stable_partition
requires bidirectional iterators, whereas std::partition
can operate on forward ones. However, on bidirectional iterators it is more efficient:
Complexity (
std::partition
)Given
N = std::distance(first,last)
,Exactly
N
applications of the predicate. At mostN/2
swaps ifForwardIt
meets the requirements ofLegacyBidirectionalIterator
, and at mostN
swaps otherwise.
If relative order of elements after partitioning is not important, use std::partition
.
Upvotes: 4
Reputation: 29985
"stable" means the order of equivalent elements won't change:
std::stable_partition
from cppreference.com:
Reorders the elements in the range [first, last) in such a way that all elements for which the predicate
p
returnstrue
precede the elements for which predicatep
returnsfalse
. Relative order of the elements is preserved.
Upvotes: 7
Reputation: 3275
The best way to figure this out is probably with an example. Let me plagiarize the example from cppreference here:
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> v{0, 0, 3, 0, 2, 4, 5, 0, 7};
std::stable_partition(v.begin(), v.end(), [](int n){return n>0;});
for (int n : v) {
std::cout << n << ' ';
}
std::cout << '\n';
}
Running this one gets you: 3 2 4 5 7 0 0 0 0
. 3, 2, 4, 5, 7 are equivalent with respect to the relation defined by the > 0
predicate and as expected they are not reordered.
However, if you replace stable_partition
with partition
for the same example you get: 7 5 3 4 2 0 0 0 0
. This time keeping the order of the equivalent elements was not guaranteed and obviously it wasn't.
Upvotes: 7